[angular2 rc1]
是否有可能有这样的组件:
export class MyComp {
@Output() myEvent = new EventEmitter(false)
ngOnDestroy() {
this.myEvent.emit('ngOnDestroy hook');
}
}
Run Code Online (Sandbox Code Playgroud)
并在父母中抓住它:
<myComp (myEvent)="test($event)"></myComp>
这似乎是不可能的,但我想明白为什么?
我知道我可以使用服务来完成.
服务是一个很好的解决方案,但您想了解原因:
在调用ngOnDestroy()之前,通过angular取消订阅.这种自动化的发生是因为您订阅了模板,angular会解析模板并且知道足够的知识.
Angular为每个组件生成一个工厂,此过程称为代码生成,由angular创建的工厂函数返回根据组件的元数据创建的唯一View类型的实例,该元数据继承AppView类.
组件实例的整个生命周期由视图管理.例如,更改检测,当然还有生命周期挂钩.
在调用ngOnDestroy生命周期钩子之前(通过组件的内部视图),会调用内部销毁函数,它会为您进行一些清理.其中一项清理操作是取消订阅所有事件,例如点击,鼠标移动和自定义事件,这些事件是子组件中定义的@Output发射器.
这是静态完成的,这意味着代码生成器知道事件订阅,因此它添加了硬编码逻辑来删除它.这是一件非常重要的事情,它可以节省大量样板代码并防止内存泄漏 - 框架可以为您清理.
同样重要的是要注意角度可以做到这一点,因为它有很多关于正在发生的事情的元数据.它知道它是一个订阅,因为它解析模板并找到一个事件表达式(例如:)(click)="something()",也因为MyComp中的@Output装饰器
你可以在很清楚地看到逻辑APPVIEW -类LINK 每个视图继承自APPVIEW和器械(除其他事项外)被调用函数destroyInternal.命令是在销毁destroyLocal()时调用(在AppView上定义),destroyLocal将清理所有订阅和一次性项,然后它将调用destroyInternal,然后destroyInternal将在组件的实例上调用ngOnDestroy().
现在,服务可能是一个很好的解决方案,但如果您了解正在发生的事情,您可以在没有外部服务的帮助下解决这个问题,这非常简单.我们现在知道,angular将取消订阅模板中注册的订阅,如果我们手动注册(即:使用代码),我们将能够触发事件.
虽然简单,但它有一些样板,因为我们需要:
ngAfterViewInit触发生命周期钩子之后才能这样做.myEvent.complete().它会为我们处理一切.这是destroy函数:
ngOnDestroy() {
this.myEvent.emit('ngOnDestroy hook');
this.myEvent.complete();
}
Run Code Online (Sandbox Code Playgroud)
这是MyApp组件:
export class MyApp {
displayComp = true
@ViewChild('mycomp', {read: MyComp}) myComp: MyComp;
constructor() {}
ngAfterViewInit() {
this.myComp.myEvent.subscribe( () => alert('myApp > receive event via MANUAL Subscription'));
}
test(e) {
alert('myApp > receive event');
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个工作的plunker - LINK
更新:我刚刚在角度回购中发现了这个问题的未决PR,现在仍然没有合并12天,需要时间来合并社区贡献,所以让我们希望它将落入下一个RC.
| 归档时间: |
|
| 查看次数: |
1309 次 |
| 最近记录: |