Angular——How does a child component receive the dynamic value passed by the parent component?

During the development process, it is very common for a parent component to pass a value to a child component. Today we will talk about what accidents may occur when a parent component passes a value to a child component, and under what circumstances the child component cannot receive the latest value passed by the parent component;

Passing value:

  1. Basic data type : The parent component passes the basic data type to the child component , and the child component uses variables to receive the passed value; when the passed value changes, the value received by the child component will also change accordingly;

  2. Reference data type : When the data object (object or reference type) passed by the parent component to the child component changes, the value received by the child component will not necessarily change accordingly;

The following are some scenarios where variables in child components do not update automatically:

  1. The input property is an object or reference type : If the input property passed by the parent component to the child component is an object or reference type (such as an array); and the properties of the object are modified or reassigned in
    the parent component , the child component The variables themselves do not change. The change detection mechanism only detects changes in the object or reference itself , but does not deeply observe changes in the properties or content inside the object. In this case, manual processing is required to ensure that the variables in the child component are updated, which can be achieved by using the OnChanges life cycle hook, set method to receive, and subscribe to changes in the Input property.
    原因:
  2. Use @ViewChild or a service to share data : If a parent component passes data to a child component through @ViewChild or a service (such as a shared service), variables in the child component usually do not update automatically. This is because the data provided by @ViewChild or the service is a separate instance and is not directly related to the data in the parent component. In this case, you need to manually update the variables in the subcomponent, such as using a subscription mechanism or event triggering.

for example:

1. The subcomponent uses the set method to receive the passed value

// 父组件
@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;
  }
}

In the above example, the parent component passes data to the child component's data input property through the parentData object. The child component receives this data using the set method and stores it in the private variable _data.

When the "Change Data" button is clicked, the changeData() method of the parent component will modify the value of parentData.value to 'Updated data'. At this time, the set method in the child component will be triggered and the new data object { value: 'Updated data' } will be received. Subcomponents can process the data accordingly inside the set method to update the status of the subcomponent.

The triggering of the set method is automatically handled by Angular's change detection mechanism , and there is no need to manually trigger the method.

set method trigger timing

  1. Triggered during initialization : When the data passed by the parent component is passed to the child component 初始化, the set method will be triggered for the first time during the creation and rendering process of the child component. This is the time to set initial values.

  2. Triggered when properties change : If the data of the parent component changes (for example, due to user interaction or asynchronous request, etc.), Angular's change detection mechanism will detect the change of properties and trigger the set method in the child component, thereby updating the child component's Corresponding properties.

get method trigger time

The get method is triggered automatically when the child component actively reads the property value, rather than by Angular's change detection mechanism . Therefore, it does not fire every time the property changes. The get method will be called only when the child component needs to get the property value.
For example, the get method will be called when using an interpolation expression, binding a property in the child component's template, or directly accessing the property in the child component's TypeScript code.

2. Use ngOnChanges life cycle hook

In this hook, listen for changes in the input properties passed in by the parent component, and manually update the variables inside the child component when they change. Through the SimpleChange object, the new value and the old value can be obtained for comparison, so as to perform corresponding processing.

// 父组件
@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 uses static: false to pass data

If the parent component passes data to the child component through @ViewChild or a service (such as a shared service) and uses it static: true, the child component will usually not update automatically when the parent component's value changes.

Instead, static: falsewhen the parent component's value changes, the child component will update accordingly.

Principle:
When using @ViewChild to obtain a reference to a subcomponent, if static is set to false, it will make @ViewChild
a query that will requery the subcomponent at each change detection. This means that if the parent component's value changes, the child component's reference will be queried again and updated.

In the parent component, obtain the reference of the child component through @ViewChild and pass the value to the child component:

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);
  }
}

In the child component, define a property to receive the parent component's value and display that data in the template:

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;
  
}

In the above example, when the parent component's updateData method is called, it updates the value of parentData and passes the new value to the child component's data property. Since @ViewChild uses static: false, the reference of the child component will be re-queried, and the child component will obtain the new value and update it during change detection.

In summary, if you use @ViewChild and set static: false, when the value of the parent component changes, the child component will also update accordingly. This allows parent components to directly affect the state and behavior of child components.

4. ViewChild uses static: true to pass data

When using @ViewChild to obtain a reference to a subcomponent, if static is set to true, it will make @ViewChild a static query and only query once when the component is initialized . This means that the child component will only get the initial value of the parent component and will not automatically update as the parent component's value changes.

In this case, you need to manually update the variables in the child component to reflect the changes in the parent component. You can use subscription mechanisms, event triggering, etc. to notify child components to update when the value of the parent component changes.

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); // 手动更新子组件中的变量
  }
}

In the child component, define a method to receive the parent component's value and display that data in the template:

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;
  }
}

In the above example, when the parent component's updateData method is called, it updates the value of parentData and manually calls the child component's updateData method to update the variables in the child component.

Guess you like

Origin blog.csdn.net/weixin_45678402/article/details/132149090