将元素的宽度传递给我自己的指令时出现 ExpressionChangedAfterItHasBeenCheckedError。
ExpressionChangedAfterItHasBeenCheckedError when passing the width of an element to my own directive.
我为 table header 创建了自己的指令(thead 标签)。这使得 table 的 header 是 "sticky"(具有固定位置并且在滚动期间可见 table)。看起来像这样:
sticky.directive.ts
const NAVBAR_HEIGHT = 55;
@Directive({
selector: '[sticky]',
})
export class StickyDirective implements AfterViewInit {
@Input()
@HostBinding('style.width.px')
stickyWidth: string;
topPosition: number;
constructor(private _element: ElementRef, private _window: WindowRef) { }
ngAfterViewInit() {
let boundingClientRect = this._element.nativeElement.getBoundingClientRect();
this.topPosition = boundingClientRect.top - NAVBAR_HEIGHT;
}
@HostListener('window:scroll', ['$event'])
handleScrollEvent(e) {
if (this._window.nativeWindow.pageYOffset > (this.topPosition) ) {
this._element.nativeElement.classList.add('stick');
} else {
this._element.nativeElement.classList.remove('stick');
}
}
}
并这样称呼:
<div class="card-block" >
<table #table class="table table-bordered">
<thead sticky [stickyWidth]="table.offsetWidth">
它工作正常,但在控制台中出现错误:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '1632'. Current value: '1615'.
at viewDebugError (core.es5.js:8633)
at expressionChangedAfterItHasBeenCheckedError (core.es5.js:8611)
at checkBindingNoChanges (core.es5.js:8775)
at checkNoChangesNodeInline (core.es5.js:12329)
at checkNoChangesNode (core.es5.js:12303)
at debugCheckNoChangesNode (core.es5.js:12922)
at debugCheckDirectivesFn (core.es5.js:12824)
at Object.View_PageListComponent_0.co [as updateDirectives] (PageListComponent.html:23)
at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:12806)
at checkNoChangesView (core.es5.js:12123)
at callViewAction (core.es5.js:12487)
任何人都可以解释我做错了什么?如何保护我的应用程序免受此异常的影响,或者创建类似指令的正确方法是什么?提前致谢
您更新 table.offsetWidth
的那一刻发生在 Angular 完成它的 changeDetection
周期之后。
最好分享代码,但如果没有看到它,您可能需要执行以下操作:
在更好和适当的时机移动更新,并确保更改过程是单向流程。
更新后使用detectorRef.detectChanges()
将更新放在 setTimeout 中
他们中的任何一个都可以,但最好是第一个,其他是你最后的选择
我为 table header 创建了自己的指令(thead 标签)。这使得 table 的 header 是 "sticky"(具有固定位置并且在滚动期间可见 table)。看起来像这样:
sticky.directive.ts
const NAVBAR_HEIGHT = 55;
@Directive({
selector: '[sticky]',
})
export class StickyDirective implements AfterViewInit {
@Input()
@HostBinding('style.width.px')
stickyWidth: string;
topPosition: number;
constructor(private _element: ElementRef, private _window: WindowRef) { }
ngAfterViewInit() {
let boundingClientRect = this._element.nativeElement.getBoundingClientRect();
this.topPosition = boundingClientRect.top - NAVBAR_HEIGHT;
}
@HostListener('window:scroll', ['$event'])
handleScrollEvent(e) {
if (this._window.nativeWindow.pageYOffset > (this.topPosition) ) {
this._element.nativeElement.classList.add('stick');
} else {
this._element.nativeElement.classList.remove('stick');
}
}
}
并这样称呼:
<div class="card-block" >
<table #table class="table table-bordered">
<thead sticky [stickyWidth]="table.offsetWidth">
它工作正常,但在控制台中出现错误:
ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '1632'. Current value: '1615'.
at viewDebugError (core.es5.js:8633)
at expressionChangedAfterItHasBeenCheckedError (core.es5.js:8611)
at checkBindingNoChanges (core.es5.js:8775)
at checkNoChangesNodeInline (core.es5.js:12329)
at checkNoChangesNode (core.es5.js:12303)
at debugCheckNoChangesNode (core.es5.js:12922)
at debugCheckDirectivesFn (core.es5.js:12824)
at Object.View_PageListComponent_0.co [as updateDirectives] (PageListComponent.html:23)
at Object.debugUpdateDirectives [as updateDirectives] (core.es5.js:12806)
at checkNoChangesView (core.es5.js:12123)
at callViewAction (core.es5.js:12487)
任何人都可以解释我做错了什么?如何保护我的应用程序免受此异常的影响,或者创建类似指令的正确方法是什么?提前致谢
您更新 table.offsetWidth
的那一刻发生在 Angular 完成它的 changeDetection
周期之后。
最好分享代码,但如果没有看到它,您可能需要执行以下操作:
在更好和适当的时机移动更新,并确保更改过程是单向流程。
更新后使用
detectorRef.detectChanges()
将更新放在 setTimeout 中
他们中的任何一个都可以,但最好是第一个,其他是你最后的选择