使用Angular时,更改检测会运行并检查UI的某些部分是否需要刷新/重新渲染。
有生命周期挂钩,但是......我无法找到事件/ hook / observable来监听视图更改。
我称之为视图更改?当Angular发现模型中存在需要在视图上更新的更改时。它可能是因为变量绑定或任何表达式。依赖ngOnChanges
生命周期挂钩时,我们只会收到有关@Input
更改的通知。但变化可能来自各种来源。
有关基本实施,请参阅this plunker。您可以打开控制台以查看console.log
中的ngOnChanges
。
输入值输入会更改传递给@Input
的组件的值。 ngOnChanges
可以检测到这种变化。
服务价值输入会更改在我们的组件内显示的某些共享服务中存储的值。 ngOnChanges
未检测到此情况,如果我们使用OnPush
检测策略,我们的组件将不会看到此更改。
但在我们的情况下,我们不想使用OnPush
,我们希望能够听取此视图更改。
在这个例子中,我们使用一个简单的输入来执行一些更改,但在现实世界中,这可能是一些异步回调......
我寻找由ViewRef
或类似内容提供的通用内容,因为它可以是执行需要检测的更改的任何Component
或TemplateRef
。
我不能依赖于Component内部实现或服务,它必须是组件不可知的。我的真实用例是检测附加到TemplateRef
Overlay的@angular/cdk
的变化。我需要收到有关更改的通知,因此我可以告诉叠加层更新其位置。
tooltip.directive.ts
@Directive({
selector: "[appTooltip]"
})
export class TooltipDirective implements OnInit, OnDestroy {
@Input("appTooltip") templateRef: TemplateRef<any>;
private _overlayRef: OverlayRef;
private _portal: TemplatePortal<any>;
constructor(private _viewContainerRef: ViewContainerRef, private _injector: Injector, private _overlay: Overlay) {}
ngOnInit(): void {
this._overlayRef = this._overlay.create();
this._portal = new TemplatePortal(this.templateRef, this._viewContainerRef);
}
@HostListener("mouseenter")
show() {
this._overlayRef.attach(this._portal);
}
@HostListener("mouseleave")
hide() {
this._overlayRef.detach();
}
ngOnDestroy(): void {
this._overlayRef.dispose();
}
/** I need to call this when changes are detected inside the templateRef. */
onTemplateChange() {
this._overlayRef.updatePosition();
}
}
app.component.html
<ng-template #myTemplate>
<h3>Some {{ variable }} bindings</h3>
<app-custom-component [withInput]="someVariable"></app-custom-component>
<app-other-component></app-other-component>
</ng-template>
<p>Show tooltip when hover <span [appTooltip]="myTemplate">this</span>.</p>
在此示例中,ng-template
元素可以包含开发人员想要的任何内容,TooltipDirective
不知道您可以在ng-template
内放置什么。
CustomComponent
可以根据您想要的任何内容更新其视图,并且不一定要调用ngOnChanges
。但它的视图已更新,因此Angular知道它需要更新模板。