子组件与父组件之间的数据共享



Angular 提供了在父组件和子组件之间传递数据的方法。Angular 提供了两个装饰器,@Input 和 @Output。Input 装饰器使用子组件属性将值从父组件传递到子组件。Output 装饰器使用子组件发出的事件将值从子组件传递到父组件。父组件必须监听来自子组件的更改事件,捕获事件信息并使用它。

让我们在本节学习如何使用 Input 和 Output 装饰器。

@Input

配置 Input 装饰器非常简单。只需将 Input 装饰器附加到子组件中的属性,然后通过子组件属性从父组件传递数据。

假设我们想将计数器从父组件传递到子组件。

步骤1:在子组件中创建一个名为 counter 的属性,并用 @Input 装饰它。

@Input() counter: number = 0;

这里:

  • @Input() 是装饰器

  • counter 是输入属性

  • number 是输入属性的数据类型,它是可选的

  • 0 是计数器的初始值。如果没有提供输入,将使用此值。

步骤2:在父组件中初始化一个变量,例如 counterValue。

counterValue: number = 10

步骤3:使用子组件属性 (counter) 从父组件传递 counter 输入。

<app-child-component [counter]="counterValue" />

步骤4:最后,根据需要在子组件模板中使用 counter 值。

counter: {{counter}}

让我们创建两个组件,父组件和子组件,然后尝试将数据从父组件传递到子组件并在子组件中渲染它。

步骤1:使用 Angular CLI 创建父组件 InOutSample,如下所示:

$ ng generate component InOutSample
CREATE src/app/in-out-sample/in-out-sample.component.css (0 bytes)
CREATE src/app/in-out-sample/in-out-sample.component.html (28 bytes)
CREATE src/app/in-out-sample/in-out-sample.component.spec.ts (596 bytes)
CREATE src/app/in-out-sample/in-out-sample.component.ts (228 bytes)
UPDATE src/app/app.module.ts (1289 bytes)

步骤2:在组件中添加一个 counter 变量,如下所示:

import { Component } from '@angular/core';

@Component({
   selector: 'app-in-out-sample',
   templateUrl: './in-out-sample.component.html',
   styleUrls: ['./in-out-sample.component.css']
})
export class InOutSampleComponent {
   counter: number = 10;
}

步骤3:使用 Angular CLI 创建一个新的子组件 InOutChildSample,如下所示:

$ ng generate component InOutChildSample
CREATE src/app/in-out-child-sample/in-out-child-sample.component.css (0 bytes)
CREATE src/app/in-out-child-sample/in-out-child-sample.component.html (34 bytes)
CREATE src/app/in-out-child-sample/in-out-child-sample.component.spec.ts (632 bytes)
CREATE src/app/in-out-child-sample/in-out-child-sample.component.ts (251 bytes)
UPDATE src/app/app.module.ts (1417 bytes)

步骤4:在子组件中添加一个 counter 属性,并用 @Input() 装饰器装饰它,如下所示:

import { Component, Input } from '@angular/core';

@Component({
   selector: 'app-in-out-child-sample',
   templateUrl: './in-out-child-sample.component.html',
   styleUrls: ['./in-out-child-sample.component.css']
})
export class InOutChildSampleComponent {
   @Input() counter : number = 0;
}

步骤5:打开子组件模板 in-out-child-sample.component.html 并使用 counter 属性,如下所示:

<div>
   <p>Counter: {{counter}}</p>
</div>

步骤6:打开父组件模板 in-out-sample.component.html 并渲染子组件以及 counter 属性,如下所示:

<app-in-out-child-sample [counter]="counter" />

步骤7:打开 app 组件的模板并渲染父组件,如下所示:

<app-in-out-sample />

<router-outlet></router-outlet>

步骤8:最后,运行应用程序并检查计数器是否显示从父组件传递的值,如下所示:

Passed Parent Component

让我们尝试使用按钮和点击事件更改父组件中的 counter 变量,然后查看它是否会影响子组件。

步骤1:在父组件中添加一个函数来递增 counter 值,如下所示

inc() {
   this.counter++
}

步骤2:在父组件的模板中添加一个按钮并绑定该函数,如下所示:

<button (click)="inc()">Increment counter</button>

<app-in-out-child-sample [counter]="counter" />

步骤3:最后,运行应用程序并检查父组件中变量的更改是否反映在子组件中。

Counter Increment

@Output

Output 装饰器与 Input 装饰器非常相似,只是输出实际上是一个事件发射器,它与事件一起传递数据(输出)。父组件可以订阅子组件中的事件,并在子组件中数据更改时从子组件获取发射的值。

步骤1:通过使用 Output 装饰器创建子组件中的事件发射器。

@Output() counterEvent = new EventEmitter<number>();

步骤2:当子组件中的数据发生更改时发出 counter 事件。

this.counterEvent.emit(changedValue)

步骤3:在父组件中捕获事件并从回调函数中获取数据。

<parent-component (counterEvent)="get($event)" />

步骤4:在父组件中对捕获的值执行任何操作。

让我们在子组件 InOutChildSample 组件中编写一个 Output 装饰器,并尝试从父组件 InOutSample 组件获取输出。

步骤1:在子组件 in-out-child-sample.component.ts 中创建一个输出事件发射器,如下所示:

@Output() counterEvent = new EventEmitter<number>();

步骤2:创建一个方法,通过在子组件 in-out-child-sample.component.ts 中发射事件以及 counter 数据来传递 counter 的值

passCounterToParent() {
   this.counterEvent.emit(this.counter)
}

子组件的完整列表如下:

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
   selector: 'app-in-out-child-sample',
   templateUrl: './in-out-child-sample.component.html',
   styleUrls: ['./in-out-child-sample.component.css']
})
export class InOutChildSampleComponent {
   @Input() counter : number = 0;
   @Output() counterEvent = new EventEmitter<number>();
   
   passCounterToParent() {
      this.counterEvent.emit(this.counter)
   }

}

步骤3:打开子组件模板 in-out-child-sample.component.html 并添加一个按钮,以便在用户单击按钮时调用 counter 事件

<div>
   <p>Counter: {{counter}}</p>
   
   <button (click)="passCounterToParent()">Pass Counter to Parent</button>
</div>

这里:

  • click 是按钮点击事件,它被配置为在点击时运行 passCounterToParent() 函数。

步骤4:在父组件中添加一个变量来保存通过子组件事件传递的输出数据。

childCounter: number = 0

步骤5:在父组件中添加一个函数来获取通过子组件事件传递的输出数据。

get(val: number) {
   this.childCounter = val;
}

父组件的完整列表如下:

import { Component } from '@angular/core';
@Component({
   selector: 'app-in-out-sample',
   templateUrl: './in-out-sample.component.html',
   styleUrls: ['./in-out-sample.component.css']
})
export class InOutSampleComponent {
   counter: number = 10;
   childCounter: number = 0;
   
   inc() {
      this.counter++
   }   
   get(val: number) {
      this.childCounter = val;
   }
}

步骤6:打开父组件模板 in-out-sample.component.html 并订阅子组件的事件 counterEvent 并将 get 方法设置为回调函数,如下所示:

<button (click)="inc()">Increment counter</button>
<p>Data from child: {{childCounter}}</p>
<app-in-out-child-sample [counter]="counter" (counterEvent)="get($event)" />

这里:

  • counterEvent 是来自子组件的事件

  • counterEvent 是回调函数。$event 将保存当前的 counter 值。

  • childContent 是来自子组件的数据

步骤7:最后,运行应用程序,您将看到当单击子组件中的按钮时,子组件会将更新的 counter 值发送到父组件。

updated Counter

总结

Input 和 Output 装饰器简化了在父组件和子组件之间传递数据,并提供了父组件和子组件之间丰富的交互。

广告
© . All rights reserved.