视频回放 【34.2】工程的进一步改造—— 善用 @ViewChild

应用场景

这是一个带有数据交互的网页,如下图。

上半部分实现添加商品,下半部分是商品列表展示。 当添加一个商品后, 商品列表会自动展示出来,无需刷新页面。

image.png

实现思路:

在直播课程中,我们讲述了它的实现方法, 当时是通过 @Output() 装饰符实现的。 @Output() 理解起来还是有些“绕”。
这次,我们换一种实现方法, 通过 @ViewChild() 装饰符来实现。

关于 @ViewChild()

@Input@Output() 一样, @ViewChild 也是一个很重要的 Decorator (装饰符), 它的应用场景是:
当Parent component 对 child component 进行存取操作时,可用到 @ViewChild

关键技术点

在 Parent Component ,要用到 AfterViewInit

按照 Angular 机制, 我们可以在 parent component 中,通过 @ViewChild() decorator (装饰符)来声明一个属于 child component 的成员属性变量, 然后,就可以对这个 child component 进行存在操作,比如: 调用 child component 的属性变量,调用 child component 的方法。

@ViewChild() 里面的参数,要传入所引入的 child component。

需要注意的是: 要想通过 @ViewChild() 存取 child component 的 pubic field (默认的是 pubic 属性), 必须在 ngAfterViewInit() lifecycle hook 中才能抓到它,不可以在 ngOnInit() 中。

说了这么多, 还是上代码吧!

代码实现

实现思路:

把整个页面放在一个component中 (home.component), 下方的商品列表放在另外一个独立的 component 中(product-list.component)。 首页(home)是一个筐,里面有多个 component 组成。

// home.component.html

创建商品

>

注意上面的代码:

>

// home.component.ts
import { Component, OnInit, ViewChild ,AfterViewInit } from '@angular/core';

import {ProductListComponent}   from '../product-list/product-list.component'

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit, AfterViewInit {

  @ViewChild (ProductListComponent)  private  productListComponent : ProductListComponent; 

   title: string;
   price:  string; 

  ngAfterViewInit(): void {   }

  constructor() { }

  ngOnInit() {
  }
   
  createProduct(){
    let myProduct : any = {
     title: this.title,
     price: this.price,
    };
    this.productListComponent.addProduct( myProduct )
  }
}

注意以上关键代码:

@ViewChild (ProductListComponent) private productListComponent : ProductListComponent;

再来看商品列表组件的实现

// product-list.component.html

商品列表

商品名称 商品价格
{{p.title}} {{p.price}}

// product-list.component.ts 
import { Component, OnInit } from '@angular/core';
import { Product } from "../product";

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {

  products: Product[];
  myProduct: any; 
  constructor() {
    this.products = new Array ();    // 必须的,否则报错, 创建对象的实例

   }
  ngOnInit() {

    this.products = [
      { title: "第 1 件商品", price: 11 },
      { title: "第 2 件商品", price: 22 },
      { title: "第 3 件商品", price: 33 },
      { title: "第 4 件商品", price: 44 },
      { title: "第 5 件商品", price: 55 },
    ];
  
  }

  addProduct( obj: any ){
      this.myProduct = {
      title :  obj.title,
      price:   obj.price
    }
    this.products.push( this.myProduct );
    console.log("收到了来自 child 组件的数据",this.products);
   }
}

product.ts

export class Product {
    title : string;
    price : number; 
}

小结

当一个页面由多个组件构成,且组件之间有数据交互发生时, 可以通过 @ViewChild 装饰符来实现。 可以这样说, 只要是 UI 相关的开发,都要解决 组件之间的数据交互问题, 不同框架的命名方式都很接近。都带有 child 字样,比如 iOS 中的 addChildViewController 等等。 一通百通!

你可能感兴趣的:(视频回放 【34.2】工程的进一步改造—— 善用 @ViewChild)