Angular 角度8使元素为正方形抛出错误:表达式ChangedTerithasBeenCheckedError
我想动态地做一个div正方形。我找到了解决办法 它确实有效,但这个错误使我不安。谁能帮我摆脱那个错误Angular 角度8使元素为正方形抛出错误:表达式ChangedTerithasBeenCheckedError,angular,angular8,Angular,Angular8,我想动态地做一个div正方形。我找到了解决办法 它确实有效,但这个错误使我不安。谁能帮我摆脱那个错误 提前感谢它在开发模式下工作,但在生产构建中可能无法正常工作。试着看看这个,理解这个错误意味着什么 要消除此错误,可以在设置高度后手动强制再次运行 我创造了简单的 HTML: <div #div (window:resize)="0" [ngStyle]="{'height.px': dynamicDivHeight }"></div> ... export class
提前感谢它在开发模式下工作,但在生产构建中可能无法正常工作。试着看看这个,理解这个错误意味着什么 要消除此错误,可以在设置高度后手动强制再次运行 我创造了简单的 HTML:
<div #div (window:resize)="0" [ngStyle]="{'height.px': dynamicDivHeight }"></div>
...
export class Component implements AfterViewInit {
@ViewChild('div', { static: false } ) div: ElementRef<HTMLDivElement>; // element reference
dynamicDivHeight: number = 1;
constructor(private changeDetectorRef: ChangeDetectorRef) {
}
ngAfterViewInit() { // if you are working with native html elements, you should be doing it in AfterViewInit hook
this.dynamicDivHeight = this.div.nativeElement.offsetWidth; // set the dynamic height
this.changeDetectorRef.detectChanges(); // manually force change detection
}
}
TS:
<div #div (window:resize)="0" [ngStyle]="{'height.px': dynamicDivHeight }"></div>
...
export class Component implements AfterViewInit {
@ViewChild('div', { static: false } ) div: ElementRef<HTMLDivElement>; // element reference
dynamicDivHeight: number = 1;
constructor(private changeDetectorRef: ChangeDetectorRef) {
}
ngAfterViewInit() { // if you are working with native html elements, you should be doing it in AfterViewInit hook
this.dynamicDivHeight = this.div.nativeElement.offsetWidth; // set the dynamic height
this.changeDetectorRef.detectChanges(); // manually force change detection
}
}
。。。
导出类组件实现AfterViewInit{
@ViewChild('div',{static:false})div:ElementRef;//元素引用
dynamicDivHeight:数字=1;
构造函数(专用changeDetectorRef:changeDetectorRef){
}
ngAfterViewInit(){//如果您使用的是本机html元素,那么应该在AfterViewInit钩子中进行
this.dynamicDivHeight=this.div.nativeElement.offsetWidth;//设置动态高度
this.changeDetectorRef.detectChanges();//手动强制更改检测
}
}
这是因为在开发模式下,angular检查值在更新绑定后是否没有更改。在两个值之间进行更改可能会产生副作用,例如没有显示正确的值(请参阅良好的解释)
在您的示例中:
- 更改检测运行
- 尚未创建div
- angular将值1指定给div的
属性style.height
- 浏览器将绘制div
- 再次执行角度变化检测(仅在开发模式下)
- div存在,因此
值不再是1。Angular然后抛出一个style.height
错误表达式ChangedTerithasBeenCheckedError
ChangeDectorRef.detectChanges()
将更改通知angular。为此,您可以调用组件的方法,因为您不能直接从模板调用它
组件。ts
lastWidth = 1;
@ViewChild('div', {static: true}) div: ElementRef;
constructor(private cdr:ChangeDetectorRef)
{
}
getWidth()
{
if(this.div)//Wzit until element is created
{
//Only call detectChanges if the previous value has changed
if(this.div.nativeElement.offsetWidth != this.lastWidth)
{
this.lastWidth = this.div.nativeElement.offsetWidth ;
this.cdr.detectChanges();
}
}
return this.lastWidth;
}
component.html
<div #div (window:resize)="0" [ngStyle]="{'height.px': getHeight() }">
我创建了一个stackblitz,您可以动态调整div的大小
注意:您还可以在
setTimeout
调用中包装更改,这也可以解决问题。但是,这将再次为整个应用程序运行更改检测,而不仅仅是您感兴趣的组件 此问题仅在开发模式下发布。在AngularJS中引入它是为了避免摘要循环中的循环问题(AngularJS中的问题)
在绑定上成功运行更改检测循环后,Angular再次通过运行更改检测来检查绑定是否已更改。若任何值发生变化,Angular将在控制台中抛出此错误
请通过这个有趣的博客来了解
如上所述,这是因为Angular运行另一个循环来检查任何绑定的值是否已更改。因此,通过使用setTimeout异步运行,可以轻松跳过连续的更改
setTimeout(() => {
this.lastWidth = this.div.nativeElement.offsetWidth;
});
您还可以按照上面的回答手动使用更改检测
请参阅此工作stackblitz:“
setTimeout
触发整个应用程序的更改检测,而detectionChanges
仅对当前组件及其子组件执行此操作。实际上,您可以使用CSS技巧,根据简单的填充属性以任何比率提供div。这里你可以看几个例子。我相信如果你需要用宽度来计算高度就足够了