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

相关推荐
我曾经是个程序员4 分钟前
鸿蒙学习记录
开发语言·前端·javascript
kkflash39 分钟前
提升专业素养的实用指南
学习·职场和发展
羊小猪~~19 分钟前
前端入门之VUE--ajax、vuex、router,最后的前端总结
前端·javascript·css·vue.js·vscode·ajax·html5
摸鱼了34 分钟前
🚀 从零开始搭建 Vue 3+Vite+TypeScript+Pinia+Vue Router+SCSS+StyleLint+CommitLint+...项目
前端·vue.js
1 9 J43 分钟前
数据结构 C/C++(实验五:图)
c语言·数据结构·c++·学习·算法
程序员shen1616111 小时前
抖音短视频saas矩阵源码系统开发所需掌握的技术
java·前端·数据库·python·算法
Ling_suu1 小时前
SpringBoot3——Web开发
java·服务器·前端
Yvemil71 小时前
《开启微服务之旅:Spring Boot Web开发》(二)
前端·spring boot·微服务
hanglove_lucky1 小时前
本地摄像头视频流在html中打开
前端·后端·html
维李设论1 小时前
Node.js的Web服务在Nacos中的实践
前端·spring cloud·微服务·eureka·nacos·node.js·express