如何订阅Angular中的实际视图更改?

时间:2017-12-30 00:00:27

标签: angular

使用Angular时,更改检测会运行并检查UI的某些部分是否需要刷新/重新渲染。

有生命周期挂钩,但是......我无法找到事件/ hook / observable来监听视图更改。

我称之为视图更改?当Angular发现模型中存在需要在视图上更新的更改时。它可能是因为变量绑定或任何表达式。依赖ngOnChanges生命周期挂钩时,我们只会收到有关@Input更改的通知。但变化可能来自各种来源。

有关基本实施,请参阅this plunker。您可以打开控制台以查看console.log中的ngOnChanges

输入值输入会更改传递给@Input的组件的值。 ngOnChanges可以检测到这种变化。

服务价值输入会更改在我们的组件内显示的某些共享服务中存储的值。 ngOnChanges未检测到此情况,如果我们使用OnPush检测策略,我们的组件将不会看到此更改。

但在我们的情况下,我们不想使用OnPush,我们希望能够听取此视图更改。

在这个例子中,我们使用一个简单的输入来执行一些更改,但在现实世界中,这可能是一些异步回调......

我寻找由ViewRef或类似内容提供的通用内容,因为它可以是执行需要检测的更改的任何ComponentTemplateRef

真实用例

我不能依赖于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知道它需要更新模板。

0 个答案:

没有答案