【发布时间】:2021-06-16 14:48:33
【问题描述】:
在加载组件时,我希望您在初始化后专注于第一个元素。我找到了一个教程,但它不适合我。
https://davidmcintosh.medium.com/auto-focusing-an-angular-input-the-easy-way-part-1-dcb1799e025f
但如果我把它放在一个为 0 的计时器中,那么它会很好用。但我不想使用计时器。
ngAfterViewInit(): void {
timer(0).subscribe(() => this.firstElement.nativeElement.focus());
}
为什么我需要一个价值如此荒谬的计时器?
这是我的 HTML 代码:
<p class="news-title" tabindex="0" #firstElement>{{ 'news.title' | translate }}</p>
<ul class="news-list" role="list">
<li role="listitem" tabindex="0" class="list-item">{{ 'news.item-1' | translate }}</li>
<li role="listitem" tabindex="0" class="list-item">{{ 'news.item-2' | translate }}</li>
<li role="listitem" tabindex="0" class="list-item">{{ 'news.item-3' | translate }}</li>
</ul>
【问题讨论】:
-
ngAfterViewInit在通常的更改检测周期完成后执行。如果你在ngAfterViewInit中执行一些状态更新,你会得到可怕的ExpressionChangedAfterIthasBeenChecked错误。所以几乎每个人都会在其中执行 settimeout(..., 0) 的变体来执行额外的操作。在这种特殊情况下,鉴于您没有执行更改组件状态的操作,我会说使用timer(0)没有读取差异。顺便说一句,focus通常在input元素上执行。您希望在<p>上试用它吗? -
我需要专注,因为可访问性。
-
嗯,在 JavaScript 中需要使用
settimeout(function, 0)是很正常的。这是常见的做法,而且一直如此。您可以在组件中试验ViewChild的选项(在您发布的 sn-p 中不存在)。我想您只是不能在创建 DOM 节点的同一滴答声中调用焦点,但这只是一个猜想。 -
我建议改为查看用于处理此问题的 angular a11y accessibility cdk 指令,例如
cdkFocusInitial而不是半生不熟的东西。
标签: angular typescript settimeout