• Angular中常常需要父组件和一个或多个子组件之间共享数据。可以使用@Input@Output来实现这个模式
    • @Input()允许父组件更新子组件中的数据,父组件中存放属性值,传递给子组件
    • @Output()允许子组件向父组件发送数据,子组件中有自己的属性值,发生改变后传递给父组件,父组件再传递给其他子组件

父子组件数据传递 - 图1

  • 父组件通过子组件的自定义属性向下传递数据给子组件;子组件通过修改父组件的属性向上发送数据个父组件

    1、组件间数值传递

    1.1、创建父组件

  • 在父组件的视图文件中引用子组件,从而道道父子组件的关系

    • 在子组件中使用[属性名]='属性值'的方式将父组件中的数据绑定到子组件的属性上
      1. ==============ng-parent.component.html==============
      2. <div style="background: beige">
      3. <h1>{{loginName}}的地盘</h1>
      4. <hr>
      5. <!--子组件2-->
      6. <app-ng-child02 [c2LoginName]="loginName"></app-ng-child02>
      7. </div>
      ```typescript =============ng-parent.component.ts================= @Component({ selector: ‘app-ng-parent’, templateUrl: ‘./ng-parent.component.html’, styleUrls: [‘./ng-parent.component.css’] }) export class NgParentComponent implements OnInit {

    public loginName: string = ‘曾经会飞的鱼’;

    constructor() { }

    ngOnInit(): void { } } ```

    1.2、创建子组件

  • 子组件ChildComponent02,这个子组件仅获取父组件共享的数据,不对数据进行修改

    1. ==============ng-chilid02.component.html===============
    2. <h2>子组件02</h2>
    3. <div style="background: cornflowerblue; height: 200px">{{c2LoginName}}的博客栏</div>
    • 子组件中用于接收共享数据的属性需要使用@Input()装饰器装饰,表明是一个输入性的属性值 ```typescript ==============ng-child02.component.ts============== @Component({ selector: ‘app-ng-child02’, templateUrl: ‘./ng-child02.component.html’, styleUrls: [‘./ng-child02.component.css’] }) export class NgChild02Component implements OnInit {

    //输入性属性用于接收父组件传值 @Input() public c2LoginName: string = ‘’;

    constructor() { }

    ngOnInit(): void { } } ```

  • 父组件=>子组件传递效果:

image.png

  • 子组件ChildComponent01,这个子组件除了从获取父组件共享的数据外,还要支持修改共享的数据

    1. ==============ng-child01.component.html================
    2. <h2>子组件01</h2>
    3. 修改用户名:<input [(ngModel)]="c1LoginName"/>
    4. <button (click)="editLoginName()"> 修改</button>
    • 子组件通过触发特定的事件,将数据传递给父组件,由父组件提供事件处理方法
    • 子组件中创建EventEmitter实例对象,创建的实例对象需要使用@Output装饰器装饰
    • @Output装饰器的属性为输出属性,可以向父组件输出
    • 通过EventEmitter实例对象的emit(val)方法,发送事件 ```typescript ==================ng-child01.component.ts=============== @Component({ selector: ‘app-ng-child01’, templateUrl: ‘./ng-child01.component.html’, styleUrls: [‘./ng-child01.component.css’] }) export class NgChild01Component implements OnInit {

    @Input() public c1LoginName: string = ‘’;

    //定义事件,定义为输出型属性,向父组件输出属性 @Output() private editEvent = new EventEmitter();

    constructor() { }

    ngOnInit(): void { }

    editLoginName(): void { //调用EventEmitter对象的emit方法将事件发送出去 this.editEvent.emit(this.c1LoginName); }

}

  1. - 父组件的视图中,子标签通过`(事件名)='父组件中的处理函数'`的方式接收子组件的事件,并进行对应的逻辑处理
  2. ```html
  3. =============ng-parent.component.html================
  4. <div style="background: beige">
  5. <h1>{{loginName}}的地盘</h1>
  6. <hr>
  7. <!--子组件1-->
  8. <app-ng-child01 [c1LoginName]="loginName" (editEvent)="editLoginName($event)"></app-ng-child01>
  9. <br><hr>
  10. <!--子组件2-->
  11. <app-ng-child02 [c2LoginName]="loginName"></app-ng-child02>
  12. </div>
  1. @Component({
  2. selector: 'app-ng-parent',
  3. templateUrl: './ng-parent.component.html',
  4. styleUrls: ['./ng-parent.component.css']
  5. })
  6. export class NgParentComponent implements OnInit {
  7. public loginName: string = '曾经会飞的鱼';
  8. constructor() { }
  9. ngOnInit(): void {
  10. }
  11. //事件处理函数,参数为事件,类型为any
  12. editLoginName(val: any) {
  13. this.loginName = val;
  14. }
  15. }
  • 在组件一中输入新的loginName点击修改,查看效果

image.png

获取子组件对象的所有属性

  • 通过下列方式获取子组对象的所有参数,这种方式很少使用,谨慎使用,传参最好还是通过事件的方式,防止数据混乱错误

    1. <div style="background: beige">
    2. <h1>{{loginName}}的地盘</h1>
    3. <hr>
    4. <!--子组件1-->
    5. <app-ng-child01 #c1 [c1LoginName]="loginName" (editEvent)="editLoginName($event)"></app-ng-child01>
    6. <br><hr>
    7. <!--子组件2-->
    8. <app-ng-child02 #c2 [c2LoginName]="loginName"></app-ng-child02>
    9. <button (click)="getSubComponent()">输出子组件</button>
    10. </div
    1. @Component({
    2. selector: 'app-ng-parent',
    3. templateUrl: './ng-parent.component.html',
    4. styleUrls: ['./ng-parent.component.css']
    5. })
    6. export class NgParentComponent implements OnInit {
    7. public loginName: string = '曾经会飞的鱼';
    8. constructor() { }
    9. ngOnInit(): void {
    10. }
    11. editLoginName(val: any) {
    12. this.loginName = val;
    13. }
    14. //通过下面手段获取子组件对象所有信息
    15. @ViewChild('c1', {static: false})
    16. private child1 = null;
    17. @ViewChild('c2', {static: false})
    18. private child2 = null;
    19. getSubComponent(){
    20. //通过获取的子对象调用对应的方法
    21. this.child1.editLoginName();
    22. //通过子对象访问对应的属性
    23. console.log(this.child2.c2LoginName);
    24. }
    25. }