应用场景
这是一个带有数据交互的网页,如下图。
上半部分实现添加商品,下半部分是商品列表展示。 当添加一个商品后, 商品列表会自动展示出来,无需刷新页面。
实现思路:
在直播课程中,我们讲述了它的实现方法, 当时是通过 @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 等等。 一通百通!