如果内容被 ngif 包裹,则 viewchild nativeElement 未定义
我尝试使用画布绘制一条线,画布被
ngif
条件包裹着。
<canvas *ngIf="condition" #canvas></canvas>
<button (click)="draw()"> click Me</button>
现在我想通过
ViewChild
绘制一条线。代码如下:
condition: boolean = false;
@ViewChild('canvas', {static: false}) public canvas: ElementRef<HTMLCanvasElement>;
draw() {
this.condition = true;
var ctx = this.canvas.nativeElement.getContext("2d");
ctx.moveTo(100,0);
ctx.lineTo(100,100);
ctx.stroke();
}
不幸的是,我收到此错误:
ERROR Error: Cannot read property 'nativeElement' of undefined
我发现,如果删除
ngif
,画布渲染就会正常工作。我不明白为什么使用
ngif
时它不起作用。有人可以解释一下如何修复该代码吗?
问题在于,您将
condition
设置为
true
并立即尝试访问
this.canvas
,而它仍然是
undefined
,因为更改仍未计算。
我可以看到两种可能的解决方案:
第一种。
丑陋
的解决方案是将其包装在
setTimeout
中:
constructor(private readonly changeDetectorRef: ChangeDetectorRef) {}
draw() {
this.condition = true;
setTimeout(() => {
const ctx = this.canvas.nativeElement.getContext('2d');
ctx.moveTo(100, 0);
ctx.lineTo(100, 100);
ctx.stroke();
});
}
另一个是调用
ChangeDetectorRef.detectChanges
:
constructor(private readonly changeDetectorRef: ChangeDetectorRef) {}
draw() {
this.condition = true;
this.changeDetectorRef.detectChanges();
const ctx = this.canvas.nativeElement.getContext('2d');
ctx.moveTo(100, 0);
ctx.lineTo(100, 100);
ctx.stroke();
}
当
this.condition
为 false 时,
canvas
将不存在,并且属性
@ViewChild('canvas', {static: false}) public canvas
将未定义。
我看到
draw
方法中的
this.condition
被赋值为
true
。Angular 将在执行该函数后运行变更检测周期。因此,画布将在执行
draw
函数后出现,而我看到代码尝试在执行之前在画布上绘制。
要修复它,您可以添加超时,例如:
draw() {
this.condition = true;
setTimeout(() => {
var ctx = this.canvas.nativeElement.getContext("2d");
ctx.moveTo(100,0);
ctx.lineTo(100,100);
ctx.stroke();
}, 0)
}
使用
condition: boolean = false;
你执行条件'false',那么所有这些就不存在了:
<canvas *ngIf="condition" #canvas>
</canvas>
,所以 #canvas 也不会退出。 然后,在ts代码组件中,childview('canvas')未定义。这就是原因。