Angular中的ngOnchange()的汇总

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

1.监听的对象

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

2.触发时机

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

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

3.参数:SimpleChanges

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

  • previousValue:变化前的值。

  • currentValue:变化后的值。

  • firstChange:一个布尔值,表示该输入属性是否是第一次变化。

  • 示例:

    javascript 复制代码
    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.语法

javascript 复制代码
ngOnChanges(changes: SimpleChanges): void {
  // 处理属性变化
}

5.示例代码

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

父组件:
javascript 复制代码
@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!';
  }
}
子组件:
javascript 复制代码
@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 并没有从父组件传递任何值到子组件,或者在组件构造函数中初始化时,输入属性还没有赋值。

举个例子:

javascript 复制代码
@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']);
  }
}

父组件:

javascript 复制代码
@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

例如:

javascript 复制代码
@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()会在 输入属性的生命周期开始时触发,即使它的值没有变化,也会触发一次钩子函数。

相关推荐
知初~几秒前
Scala基础学习
开发语言·学习·scala
孜然卷k2 分钟前
前端导出word文件,并包含导出Echarts图表等
前端·javascript
家里有只小肥猫23 分钟前
uniApp小程序保存canvas图片
前端·小程序·uni-app
前端大全25 分钟前
Chrome 推出全新的 DOM API,彻底革新 DOM 操作!
前端·chrome
八角丶36 分钟前
元素尺寸的获取方式及区别
前端·javascript·html
花王江不语38 分钟前
设计模式学习笔记
笔记·学习·设计模式
冴羽44 分钟前
Svelte 最新中文文档教程(16)—— Context(上下文)
前端·javascript·svelte
前端小臻1 小时前
关于css中bfc的理解
前端·css·bfc
前端熊猫1 小时前
CSS Grid 布局学习笔记
css·笔记·学习·grid
Ama_tor1 小时前
网页制作05-html,css,javascript初认识のhtml表格的创建
javascript·css·html