在 ngAfterViewInit 处找不到 HTML 元素

问题描述 投票:0回答:1

我有一个注入 Ace 编辑器的 Angular 组件。有时在日志中(非常罕见)我可以看到以下错误:

Error: ace.edit can't find div #aceEditor
    at ie.edit (https://stepindev.com/ru/main.fcb9335868d1e005.js:1:1267133)
    at t.ngAfterViewInit (https://stepindev.com/ru/main.fcb9335868d1e005.js:1:467814)

我一直无法重现这个问题。我不明白是什么原因造成的。我的理解是,当 ngAfterViewInit 启动的那一刻,DOM 就准备好了,可以使用了。

那么问题是问题的原因是什么?

组件模板:

<div id="aceEditor" #editor></div>

<!--Don't recreate console with *ngIf. It must exists all the time to be able to capture all console input/output-->
<sid-console #console class="console" (change)="onIOAppeared()" hidden></sid-console>

<ng-content></ng-content>

ngAfterViewInit 处理程序

    import * as ace from 'ace-builds'

    ...

    ngAfterViewInit(): void {
        this.editor = ace.edit('aceEditor');
        this.editor.setTheme('ace/theme/textmate');
        this.editor.session.setMode('ace/mode/python');
        this.editor.setOptions({
            fontSize: '16pt'
        });

        this.editor.on("change", delta => this.change.emit(delta))
        window.addEventListener(this.resizeEvenName, this.resizeEventListener, false);

        // resize after all components above this one are settled. So we can get the correct "top" value
        window.setTimeout(() => this.resizeComponents(), 0);
    }

包含此组件的容器是根据 HTTP 请求动态创建的(使用 *ngIf):

<sid-robot-python-view [task]="$any(task)" *ngIf="isRobotPythonTask()" data-testId="robot-python-view"></sid-robot-python-view>

我希望错误永远不会发生。它是针对 Windows 上的 Chrome 130.0 和 Chrome 109.0 记录的。我使用 Angular 14。

angular ace-editor
1个回答
0
投票

根据Ace编辑器文档 - 编辑函数接受

element
而不是字符串,您可以尝试此方法而不是传入字符串吗?

import * as ace from 'ace-builds'
...

...
@ViewChild('aceEditor') aceEditor: ElementRef<any>;
...

ngAfterViewInit(): void {
    if(this.editor?.nativeElement) {
        this.editor = ace.edit(this.editor.nativeElement);            
        this.editor.setTheme('ace/theme/textmate');
        this.editor.session.setMode('ace/mode/python');
        this.editor.setOptions({
            fontSize: '16pt'
        });

        this.editor.on("change", delta => this.change.emit(delta))
        window.addEventListener(this.resizeEvenName, this.resizeEventListener, false);

        // resize after all components above this one are settled. So we can get the correct "top" value
        window.setTimeout(() => this.resizeComponents(), 0);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.