自学内容网 自学内容网

Angular中的ngOnchange()的汇总

ngOnChanges() 是 Angular 中的一个生命周期钩子函数,它在组件或指令的 输入属性@Input())发生变化时被调用。这个钩子可以帮助你检测输入数据的变化,并对数据变化做出反应。

1.监听的对象

  ngOnChanges() 监听的是 通过 @Input() 装饰器传递给子组件的属性。换句话说,任何标记为 @Input() 的属性都会被 ngOnChanges() 监听。具体来说,它会监听通过父组件传递给子组件的属性变化。

2.触发时机

  ngOnChanges() 会在 输入属性的值变化时被调用,且每次变化都会传递给钩子一个 SimpleChanges 对象,其中包含了该输入属性的前后值。

  • 第一次调用:在组件初始化时,如果有输入属性,ngOnChanges() 会在组件的构造函数和 ngOnInit() 之前被调用。
  • 后续调用:每次输入属性的值发生变化时,ngOnChanges() 会被再次调用。

3.参数:SimpleChanges

   ngOnChanges() 的参数是一个 SimpleChanges 对象,它是一个字典对象,包含了所有发生变化的输入属性。每个输入属性的变化信息是一个 SimpleChange 对象,它包含以下属性:

  • previousValue:变化前的值。
  • currentValue:变化后的值。
  • firstChange:一个布尔值,表示该输入属性是否是第一次变化。
  • 示例:
    ngOnChanges(changes: SimpleChanges): void {
      if (changes['inputProp']) {
        const previousValue = changes['inputProp'].previousValue;
        const currentValue = changes['inputProp'].currentValue;
        const isFirstChange = changes['inputProp'].firstChange;
        console.log(`inputProp changed from ${previousValue} to ${currentValue}`);
        console.log(`Is this the first change? ${isFirstChange}`);
      }
    }
    

4.语法

ngOnChanges(changes: SimpleChanges): void {
  // 处理属性变化
}

5.示例代码

       假设有一个父组件 ParentComponent 和一个子组件 ChildComponent,父组件向子组件传递输入属性。

父组件:
@Component({
  selector: 'app-parent',
  template: `
    <app-child [inputProp]="parentData"></app-child>
    <button (click)="changeData()">Change Data</button>
  `
})
export class ParentComponent {
  parentData = 'Hello';

  changeData() {
    this.parentData = 'Hello, Angular!';
  }
}
子组件:
@Component({
  selector: 'app-child',
  template: `<p>{{ inputProp }}</p>`
})
export class ChildComponent implements OnChanges {
  @Input() inputProp: string;

  ngOnChanges(changes: SimpleChanges) {
    if (changes['inputProp']) {
      const previousValue = changes['inputProp'].previousValue;
      const currentValue = changes['inputProp'].currentValue;
      const firstChange = changes['inputProp'].firstChange;
      console.log(`inputProp changed from ${previousValue} to ${currentValue}`);
      console.log(`Is this the first change? ${firstChange}`);
    }
  }
}

6.解析:

  • ParentComponent 中的 parentData 发生变化时,ChildComponent 中的 inputProp 将触发 ngOnChanges() 钩子。
  • SimpleChanges 对象中将包含 inputProp 属性的变化信息,其中包括前一个值、当前值和是否为首次变化的信息。

7.使用场景

  • 响应输入变化:当需要在输入数据发生变化时做一些额外处理,例如重新计算、重新加载数据等。
  • 优化性能:可以在数据变化时执行优化操作,例如避免不必要的 API 调用。
  • 数据监控:在多个输入属性同时变化时,使用 ngOnChanges() 可以监控不同输入的变化并做出响应。

8.注意事项

  • ngOnChanges() 会在每次输入属性变化时被调用,因此如果输入属性频繁变化,ngOnChanges() 也会频繁触发,可能影响性能。
  • 如果组件的输入属性没有变化,ngOnChanges() 不会被触发。
  • ngOnChanges() 仅在 @Input() 属性变化时触发,不会监控其他类型的变化(例如,组件内部的局部状态变化)。

总结:

   ngOnChanges() 监听的是组件的 输入属性(@Input(),每当父组件传递给子组件的输入属性发生变化时,ngOnChanges() 会被触发并接收一个 SimpleChanges 对象,包含所有变化的输入属性的详细信息。

  • 监听对象@Input() 属性。
  • 变化内容:父组件传递给子组件的数据变化。

附加说明:为什么有个时候可以接收到 currentValue 和 previousValue 都是 undefined 的情况?这种情况不是应该没有变化嘛?为什么可以检测到?

        在 Angular 中,如果你在 ngOnChanges() 中看到 currentValuepreviousValue 都是 undefined,这可能是由于一些特定的场景或代码逻辑导致的。下面是可能的分析:

1. 组件初始化时的行为

ngOnChanges() 会在 组件初始化时触发一次,特别是在组件的输入属性第一次被设置时。

  • 首次输入时,Angular 会触发一次 ngOnChanges(),即使没有任何显式的变化。
  • 在这个第一次触发时,previousValuecurrentValue 可能会是 undefined,因为此时 Angular 并没有从父组件传递任何值到子组件,或者在组件构造函数中初始化时,输入属性还没有赋值。

举个例子:

@Component({
  selector: 'app-child',
  template: `<p>{{ inputProp }}</p>`
})
export class ChildComponent implements OnChanges {
  @Input() inputProp: string;

  ngOnChanges(changes: SimpleChanges) {
    // 如果 inputProp 是第一次变化,可能会看到 undefined
    console.log(changes['inputProp']);
  }
}

父组件:

@Component({
  selector: 'app-parent',
  template: `<app-child [inputProp]="parentData"></app-child>`
})
export class ParentComponent {
  parentData = 'Initial value';
}

执行过程

  1. ChildComponent 第一次加载时,ngOnChanges() 会被触发。此时 inputProp 可能是 undefined,因为它是第一次接收到父组件的数据。
  2. ngOnChanges() 会触发一次,即使父组件的值是首次设置,也会传递 SimpleChanges 对象,inputProppreviousValuecurrentValue 可能都是 undefined,因为 Angular 是在首次赋值时检查的。
  3. firstChange 会是 true,表示这是第一次赋值。
2. 父组件传递的数据为 undefined

        如果父组件传递给子组件的 @Input() 属性值是 undefined,并且这个值发生了变化,ngOnChanges() 也会触发。在这种情况下,如果传递的数据本身就是 undefined,那么 previousValuecurrentValue 可能都为 undefined

例如:

@Component({
  selector: 'app-parent',
  template: `<app-child [inputProp]="parentData"></app-child>`
})
export class ParentComponent {
  parentData = undefined; // 或者 null
}

        如果父组件的 inputProp 值初始化为 undefined,当子组件的 ngOnChanges() 被调用时,changes['inputProp'] 中的 previousValuecurrentValue 可能都是 undefined,因为 inputProp 被初始化为 undefined,并且没有显式的初值。

3. 异步数据变化

        如果输入属性的值是通过异步操作(比如从 API 获取数据)赋值的,ngOnChanges() 可能会在组件初始化时被触发,但值还没有更新。

  • 在这种情况下,ngOnChanges() 会先被调用一次,此时输入属性的值可能还没有赋值或者为 undefined
  • 当异步数据到达并更新输入属性时,ngOnChanges() 会再次被调用,且这时 SimpleChanges 会包含有效的值。
4. 组件初始化与 ngOnChanges() 的触发时机

        Angular 在组件初始化时会触发 ngOnChanges(),即使输入属性的初始值是 undefined 或者 null,也会触发一次钩子函数。这时:

  • previousValue 可能是 undefined,因为组件初始化时没有值。
  • currentValue 可能也是 undefined,因为输入属性的初值可能是 undefinednull
总结

        当你看到 ngOnChanges() 中的 currentValuepreviousValue 都是 undefined 时,通常是以下几种情况之一:

  1. 组件初始化时:当组件第一次被创建并接收到 @Input() 数据时,Angular 会触发 ngOnChanges(),即使没有显式的变化,也会将 previousValuecurrentValue 都设为 undefined,尤其当输入属性还没有被赋值时。
  2. 父组件的输入值是 undefined:如果父组件传递的 @Input() 值本身是 undefined,那么 currentValuepreviousValue 也会是 undefined
  3. 异步赋值:如果输入属性的值是通过异步操作(如 HTTP 请求)传递的,可能会在初始化时出现 undefined,而在值更新后触发另一次 ngOnChanges()
再次强调:

        ngOnChanges()不是仅在值变化时触发,而是在每次输入属性的值发生变化时都会被触发,包括从undefined到undefined(即初始绑定时)。换句话说,ngOnChanges()会在 输入属性的生命周期开始时触发,即使它的值没有变化,也会触发一次钩子函数。


原文地址:https://blog.csdn.net/qq_44327851/article/details/143791769

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!