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

RMo*_*RMo 2 angular angular-lifecycle-hooks

我试图在组件初始化后在输入字段中选择一些文本。我知道我可以用 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();
  }

}
Run Code Online (Sandbox Code Playgroud)

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

ysf*_*ysf 5

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

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

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

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

回到你的问题;

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

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

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

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

它位于OnChanges挂钩之后 ,其中;

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

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

ngAfterViewInit() {
  setTimeout(() => this.input.nativeElement.select());
}
Run Code Online (Sandbox Code Playgroud)

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

ngOnChanges() {
  setTimeout(() => this.input.nativeElement.select());
}
Run Code Online (Sandbox Code Playgroud)

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

希望能帮助到你。