开发者问题收集

如果内容被 ngif 包裹,则 viewchild nativeElement 未定义

2021-08-02
691

我尝试使用画布绘制一条线,画布被 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 时它不起作用。有人可以解释一下如何修复该代码吗?

Stackblitz 示例

3个回答

问题在于,您将 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();
  }

DEMO

developer033
2021-08-02

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)
  }
IAfanasov
2021-08-02

使用

condition: boolean = false;

你执行条件'false',那么所有这些就不存在了:

<canvas *ngIf="condition" #canvas>
  
</canvas>

,所以 #canvas 也不会退出。 然后,在ts代码组件中,childview('canvas')未定义。这就是原因。

Juan Vicente Berzosa Tejero
2021-08-02