1

初始化组件后,我试图在输入字段中选择一些文本。我知道我可以用 a 来做到这一点setTimeout(),但这感觉有点太老套了。

大多数钩子在输入文本被双向绑定加载之前运行。每次有人选择其他字段时,其他人也会运行。

代码:https ://stackblitz.com/edit/angular-pxrssq

import { Component, OnInit, Input, ViewChild } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <input #input type="text" [(ngModel)]="info.one"/>
    <input type="text" [(ngModel)]="info.two"/>`,
  styleUrls: ['./child.component.css']
})
export class ChildComponent implements OnInit {
  @Input() info;
  @ViewChild('input', {static: true} ) input;

  constructor() { }

  ngOnInit() {
    this.input.nativeElement.select();
  }

}

是否有一个生命周期钩子在组件初始化之后运行一次,但在加载双向绑定之后?

4

1 回答 1

2

事实上,使用setTimeout()不是一个 hacky 解决方案,它是解决方案。因为Angular 的单向数据流规则

Angular 的单向数据流规则禁止在视图组合后对其进行更新。

为了观察此规则的后果,请尝试为on hook的info属性分配一个新值。你会得到一种Angular 的说法,即“禁止在视图组合后更新视图!”ChildComponentAfterViewInitExpressionChangedAfterItHasBeenCheckedError

由于您没有更新任何组件的数据绑定属性并且只是进行 dom 操作,因此 angular 不会引发任何错误,但它也不会反映您对 dom 的更改。

回到你的问题;

是否有一个生命周期钩子在组件初始化之后运行一次,但在加载双向绑定之后?

是的,它是AfterViewInit钩子。因为;

在调用 ngAfterViewInit 回调之前设置视图查询。

并且 DOM 更新在ngAfterViewInit被调用之前被处理,如此所述。

它出现 OnChanges钩子之后,在哪里;

当指令的任何数据绑定属性发生更改时,将调用 OnChanges。

因此,如果您希望在第一次加载组件时只选择一次文本,您应该执行以下操作。

ngAfterViewInit() {
  setTimeout(() => this.input.nativeElement.select());
}

如果您想在input父组件更改属性时选择文本(包括第一次加载),那么您需要实现OnChanges挂钩。

ngOnChanges() {
  setTimeout(() => this.input.nativeElement.select());
}

这是一个工作演示https://stackblitz.com/edit/angular-owahps

希望能帮助到你。

于 2019-06-22T19:16:52.393 回答