美文网首页
视频回放 【34.2】工程的进一步改造—— 善用 @ViewCh

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

作者: 全栈开发之道 | 来源:发表于2019-01-08 11:37 被阅读0次

应用场景

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

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

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
<div class="container">
  <h3 class="text-center"> 创建商品 </h3>
  <form >
  <div class="form-group">
    <label for="username"> 商品名称: </label>
    <input type="text" class="form-control" placeholder="请输入商品名称" [(ngModel)]= "title"  name = "key_title">
  </div>

  <div class="form-group">
    <label for="text">商品价格: </label>
    <input type="text" class="form-control" placeholder="请输入商品价格" [(ngModel)]= 'price'  name = "key_price">
  </div>

  <div class="form-group">
    <input type = "button" class = "btn btn-primary" value ="添加商品" (click)="createProduct()"> 
  </div>
</form>
</div>

<app-product-list>  </app-product-list>> 

注意上面的代码:

<app-product-list> </app-product-list>>

// 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
<div class="container">
  <h3 class="text-center">商品列表</h3>
  <table class="table table-dark table-hover table-striped">
    <thead class="thead-light">
      <tr>
        <th>商品名称</th>
        <th>商品价格</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let p of products">
        <td>{{p.title}}</td>
        <td>{{p.price}}</td>
      </tr>
    </tbody>
  </table>
</div>

// 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 <Product>();    // 必须的,否则报错, 创建对象的实例

   }
  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】工程的进一步改造—— 善用 @ViewCh

      本文链接:https://www.haomeiwen.com/subject/gfrvrqtx.html