当前位置: 首页 > news >正文

angular——子组件如何接收父组件的动态传值

开发过程中,父组件给子组件传值的情况很常见,今天我们就来聊聊父组件给子组件传值可能会发生哪些意外,什么情况下子组件无法接收到父组件最新的传值;

传值情况:

  1. 基本数据类型:父组件给子组件传递 基本数据类型,子组件使用变量接收传值;当传值发生变化,子组件接收的值也会跟着变化;

  2. 引用数据类型:当父组件传递给子组件的 数据对象(对象或引用类型) 发生变化时,子组件接收到的值不一定会跟着变化;

以下是一些情况下子组件中的变量不会自动更新的场景:

  1. 输入属性为对象或引用类型: 如果父组件传递给子组件的输入属性是一个对象或引用类型(如数组);
    并且在父组件中修改了该对象的属性或对其进行了重新赋值,子组件中的变量本身不会发生变化。
    原因:变更检测机制只会检测到对象或引用本身的变化,而不会深度观察对象内部的属性或内容的变化。
    在这种情况下,需要手动处理以确保子组件中的变量更新,可以使用 OnChanges 生命周期钩子、set方法接收、订阅 Input 属性的变化来实现。
  2. 使用 @ViewChild 或服务来共享数据: 如果父组件通过 @ViewChild 或服务(例如共享服务)来传递数据给子组件,子组件中的变量通常不会自动更新。这是因为 @ViewChild 或服务提供的数据是一个单独的实例,与父组件中的数据不直接关联。在这种情况下,需要手动更新子组件中的变量,例如使用订阅机制或事件触发等方式。

举例说明:

1. 子组件使用set方法接收传值

// 父组件
@Component({selector: 'app-parent',template: `<app-child [data]="parentData"></app-child><button (click)="changeData()">Change Data</button>`
})
export class ParentComponent {parentData = { value: 'Initial data' };changeData() {this.parentData.value = 'Updated data';}
}// 子组件
@Component({selector: 'app-child',template: `<p>{{ childData }}</p>`
})
export class ChildComponent {private _data: any;@Input()set data(value: any) {this._data = value;// 在这里可以对数据进行进一步处理}get childData(): any {return this._data;}
}

在上述示例中,父组件通过 parentData 对象将数据传递给子组件的 data 输入属性。子组件使用 set 方法接收该数据,并将其存储在私有变量 _data 中。

当点击 “Change Data” 按钮时,父组件的 changeData() 方法将修改 parentData.value 的值为 ‘Updated data’。此时,子组件中的 set 方法会被触发,并接收到新的数据对象 { value: ‘Updated data’ }。子组件可以在 set 方法内部对数据进行相应的处理以更新子组件的状态。

set 方法的触发是由 Angular 的变更检测机制 自动处理的,无需手动触发该方法。

set 方法触发时机

  1. 初始化时触发: 当父组件传递的数据被子组件初始化时,set 方法会在子组件创建和渲染过程中首次触发。这是设置初始值的时机。

  2. 属性变化时触发: 如果父组件的数据发生了变化(例如由于用户交互或异步请求等),Angular 的变更检测机制会检测到属性的变化,并触发子组件中的 set 方法,从而更新子组件的相应属性。

get 方法触发时机

get 方法的触发是由子组件主动读取属性值时自动触发的,而不是由 Angular 的变更检测机制触发的。因此,它并不会在每次属性变化时都触发。只有当子组件需要获取属性值时,get 方法才会被调用。
例如,在子组件的模板中使用插值表达式、绑定属性、或者在子组件的 TypeScript 代码中直接访问该属性时,get 方法会被调用。

2. 使用 ngOnChanges 生命周期钩子

在该钩子中监听父组件传入的输入属性变化,并在变化时手动更新子组件内部的变量。通过 SimpleChange 对象可以获取到新值和旧值进行比较,从而进行相应的处理。

// 父组件
@Component({selector: 'app-parent',template: `<app-child [data]="parentData"></app-child><button (click)="changeData()">Change Data</button>`
})
export class ParentComponent {parentData = { value: 'Initial data' };changeData() {this.parentData.value = 'Updated data';}
}// 子组件
@Component({selector: 'app-child',template: `<p>{{ childData }}</p>`
})
export class ChildComponent implements OnChanges {@Input() data: any;childData: any;ngOnChanges(changes: SimpleChanges) {if (changes.data && changes.data.currentValue) {this.childData = changes.data.currentValue;}}
}

3. ViewChild 使用static: false 传递数据

如果父组件通过 @ViewChild 或服务(例如共享服务)来传递数据给子组件,并且使用 static: true,那么当父组件的值发生变化时,子组件通常不会自动更新。

相反,使用 static: false,那么当父组件的值发生变化时,子组件也会相应地更新。

原理:
当使用 @ViewChild 来获取对子组件的引用时,如果将 static 设置为 false,它会使得 @ViewChild
成为一个查询,会在每次变更检测时重新查询子组件。这意味着如果父组件的值发生变化,子组件的引用会重新查询并得到更新。

在父组件中,通过 @ViewChild 获取子组件的引用,并传递值给子组件:

import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './child.component';@Component({selector: 'app-parent',template: `<app-child></app-child><button (click)="updateData()">Update Parent Data</button>`
})
export class ParentComponent {@ViewChild(ChildComponent, { static: false })childComponent: ChildComponent;parentData = { name: 'John', age: 25 };updateData(): void {this.parentData = { name: 'Jane', age: 30 };this.childComponent.data = this.parentData;// 或者调用子组件的方法进行更新:this.childComponent.updateData(this.parentData);}
}

在子组件中,定义一个属性来接收父组件的值,并在模板中显示该数据:

import { Component, Input } from '@angular/core';@Component({selector: 'app-child',template: `<div>Name: {{ data.name }}</div><div>Age: {{ data.age }}</div>`
})
export class ChildComponent {@Input()data: any;}

在上述示例中,当父组件的 updateData 方法被调用时,它会更新 parentData 的值,并将新值传递给子组件的 data 属性。由于 @ViewChild 使用了 static: false,子组件的引用会重新查询,在变更检测期间子组件会获取到新的值并进行更新。

总结来说,如果你使用 @ViewChild 并设置了 static: false,当父组件的值发生变化时,子组件也会随之更新。这使得父组件能够直接影响到子组件的状态和行为。

4. ViewChild 使用static: true 传递数据

使用 @ViewChild 来获取对子组件的引用时,如果将 static 设置为 true,它会使得 @ViewChild 成为一个静态查询,只在 组件初始化时 进行一次查询。这意味着子组件只会获取到父组件初始时的值,并且不会随着父组件值的变化而自动更新。

在这种情况下,需要手动更新子组件中的变量以反映父组件的变化。可以使用订阅机制、事件触发等方式,在父组件的值发生变化时通知子组件进行更新。

import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './child.component';@Component({selector: 'app-parent',template: `<app-child></app-child><button (click)="updateData()">Update Parent Data</button>`
})
export class ParentComponent {@ViewChild(ChildComponent, { static: true })childComponent: ChildComponent;parentData = { name: 'John', age: 25 };updateData(): void {this.parentData = { name: 'Jane', age: 30 };this.childComponent.updateData(this.parentData); // 手动更新子组件中的变量}
}

在子组件中,定义一个方法来接收父组件的值,并在模板中显示该数据:

import { Component } from '@angular/core';@Component({selector: 'app-child',template: `<div>Name: {{ data.name }}</div><div>Age: {{ data.age }}</div>`
})
export class ChildComponent {data: any;updateData(newData: any): void {this.data = newData;}
}

在上述示例中,当父组件的 updateData 方法被调用时,它会更新 parentData 的值,并手动调用子组件的 updateData 方法来更新子组件中的变量。

http://www.lryc.cn/news/114285.html

相关文章:

  • php 桥接模式
  • Android 13 Hotseat定制化修改——004 hotseat布局位置
  • 海外版金融理财系统源码 国际投资理财系统源码 项目投资理财源码
  • 洛谷P1162 - 填涂颜色
  • 设计模式十一:外观模式(Facade Pattern)
  • GIS和倾斜摄影的关系?
  • 【CI/CD】图解六种分支管理模型
  • LeetCode105. 从前序与中序遍历序列构造二叉树
  • 编码技巧——Sentinel的blockHandler与fallback
  • 最新成果展示:GaN基Micro-LED热学模型数据库的开发及应用
  • 【Vue3】动态组件
  • Java超级玛丽小游戏制作过程讲解 第五天 创建并完成常量类04
  • 设置浏览器兼容
  • Java # List
  • git原理与使用
  • 【C语言题解】将一句话的单词进行倒置,标点不倒置。
  • Postman 的简单使用
  • 在CentOS7安装部署GitLab服务
  • 订单系统就该这么设计,稳的一批~
  • Agents改变游戏规则,亚马逊云科技生成式AI让基础模型加速工作流
  • 详细教程:如何搭建废品回收小程序
  • 什么是双亲委派机制?
  • Mageia 9 RC1 正式发布,Mandriva Linux 发行版的社区分支
  • ChatGPT: 人机交互的未来
  • Linux 常用操作命令
  • 24届近5年重庆邮电大学自动化考研院校分析
  • 如何对oracle和mysql进行 分区分表
  • Windows下安装Sqoop
  • Chrome 谷歌浏览器,自动填充密码,提示需要输入电脑开机密码问题
  • Java技术整理(3)—— 多线程并发篇