Angular2可观察到的变化检测模板更新

克里斯

出于性能原因,我试图在组件上设置手动更改检测。

应用程序的结构:应用程序->书籍->页面

我在AppComponent中订阅了一个可观察对象,然后运行ChangeDetectorRef的“ markForCheck”方法。

这似乎会触发BookComponent(我标记为要更新的组件的子代)中的ngAfterContentChecked方法。

这使我相信父组件中的“ markForCheck”也会更新所有子组件。

但是,即使在子项(BookComponent)中执行ngAfterContentChecked,该组件的模板也不会更新!

我是否应该在每个孩子中听观察到的声音(有时在组件层次结构的多个层次中都听得到)?还是我做错了什么?为什么即使模板没有更新,ngAfterContentChecked也要在子组件中执行?

一些相关的代码。

@Component({
    selector: 'app',
    directives: [BookComponent],
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: `
        <book *ngIf="_book" [book]="_book" [style.height]="_availableDimensions.height+'px'" (window:resize)="onResize($event)"></book>
        <footer id="footer"></footer>
    `
})

export class PlayerComponent {
    ngOnInit() {
        this.initScale();
    }

initScale(){
        this._playerService.availableDimensions$.subscribe(
            availableDimensions => {
                // set local availableDimensions variable
                this._availableDimensions = availableDimensions;
                this._cd.markForCheck();
            }
        );
    }
}



@Component({
    selector: 'book',
    directives: [PageComponent],
    changeDetection: ChangeDetectionStrategy.OnPush,
    template: `
        <div id="pageScrollZone">
            <div id="pageHolder" [ngStyle]="pageHolderStyles()"></div>
        </div>
    `
})

export class BookComponent {
    constructor(
            private _cd: ChangeDetectorRef,
            private _playerService: PlayerService,
            private _config: Config
    ){}

    ngAfterContentChecked(){
// This part does execute when the observable changes
        let date = new Date();
        console.log('BOOK: '+date.getHours()+':'+date.getMinutes()+':'+date.getSeconds());
    }

    pageHolderStyles(){
// This part does NOT execute when the observable changes
        let styles = {
            marginTop: this._currentMargin.y+'px',
            transform: 'scale('+ (this._baseZoom * this._currentZoomLevel) +')'
        }

        return styles;
    }
}
丹尼斯·斯莫莱克(Dennis Smolek)

太...两件事

首先,当您使用markForCheck()时,它会在组件ITSELFROOT COMPONENT之间移动,以标记Angular应该在其上进行更改检测的路径。

摘自Thoughtram的一篇精彩文章: 树

“我们可以通过依赖注入来访问组件的ChangeDetectorRef,它带有一个称为markForCheck()的API。此方法完全可以满足我们的需要!它标记了从组件到根的路径,以进行下一次更改检测运行。”

因此,当您触发它时,它不会看它自己的孩子,而是看它的根组件。如果它的孩子们也在onPush上,他们将忽略它的更新。

我是否应该在每个孩子中听观察到的声音(有时在组件层次结构的多个层次中都听得到)?

仅当您希望所有元素都明确地onPush时。我的猜测是,如果父项确实要让Pages自动更新,那么您真幸运!如果在页面组件上使用标准策略,并Book使用onPush策略,则当检测沿树运行时,即使子级是正常组件,它也会跳过该分支。资料来源:Victor Savkin

所以,NO,你不必听观察者深刻,只是无论你想休息是。如果必须诱使它工作,每个onPush组件都不能保证性能的提高在大多数情况下,仅阻塞关键节点就足够了。

第二件事是关于ngAfterContentChecked的,这是一个已知的错误:

(完全一样)https://github.com/angular/angular/issues/7055

(相关的,关于两者的更好的讨论)https://github.com/angular/angular/issues/7054

因此,他们知道了这一点,它实际上不是在运行检测,而是触发了回调……

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章