欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ng-book札记——Angular工作方式

程序员文章站 2022-03-30 13:43:40
Angular应用由组件(Component)构成。它与AngularJS中的指令相似(directive)。 应用 一个Angular应用本质上是一个组件树。在组件树的顶层,最上级的组件即是应用本身。当启动此应用时,浏览器将渲染这个顶层组件。 Angular组件的重要特性是其可按照父子树的结构* ......

Angular应用由组件(Component)构成。它与AngularJS中的指令相似(directive)。

应用

一个Angular应用本质上是一个组件树。在组件树的顶层,最上级的组件即是应用本身。当启动此应用时,浏览器将渲染这个顶层组件。
Angular组件的重要特性是其可按照父子树的结构*组合,当每个组件渲染时,也会递归渲染其子组件。
假设有一个库存管理的应用,如下图所示:
ng-book札记——Angular工作方式
在开始写应用时,首先应该将其拆成三个组件。
标签导航组件:
ng-book札记——Angular工作方式
面包屑导航组件:
ng-book札记——Angular工作方式
产品列表组件:
ng-book札记——Angular工作方式
再进一步拆分的话,产品列表由多个产品行构成。
ng-book札记——Angular工作方式
而产品行又可以拆成产品图片,产品所属,价格显示这件小组件。
所以最终应用的树图是这样的:
ng-book札记——Angular工作方式

组件

每个组件包含三部分:

  • 组件装饰器(Component Decorator)
  • 视图(View)
  • 控制器(Controller)

以最上层的应用组件为例,这个组件的代码可能是这样的:

@Component({
  selector: 'inventory-app-root',
  template: `
  <div class="inventory-app">
  (Products will go here soon)
  </div>
  `
 })
export class AppComponent {

}

@Component就是组件装饰器,它为AppComponent类添加元数据。
上例的@Component装饰器指定了选择器(selector)——告诉Angular匹配何种元素(element),以及模板(template)——定义了视图。
模板内容可以置于其它的文件中,这时需要使用templateUrl替代template。

@Component({
  selector: 'inventory-app-root',
  templateUrl: './app.component.html'
})
export class AppComponent {

}

组件控制器通过类(class)来定义,上例的AppComponent类即是控制器。
假设要在AppComponent组件对应的视图中显示产品的信息,可以通过模板绑定的方式达成此目的。

<div class="inventory-app">
  <h1>{{ product.name }}</h1>
  <span>{{ product.sku }}</span>
</div>

{{ … }}语法被称为模板绑定,它会告诉视图使用模板中的特定数据。
组件中的核心特性之一是输入(input)与输出(output)。

<div class="inventory-app">
  <products-list
  [productList]="products"
  (onProductSelected)="productWasSelected($event)">
  </products-list>
</div>

方括号传送输入,圆括号处理输出。
借由输入绑定数据进入组件,通过输出绑定事件流出组件。
在Angular中,父组件通过输入传送数据给子组件,而子组件则通过输出传送数据给父组件。
需要接收数据的子组件要由@Input()装饰器指明对应的属性。如下例:

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

@Component({
  selector: 'my-component',
})
class MyComponent {
  @Input() name: string;
  @Input() age: number;
}

而要让父组件接收数据的子组件要使用@output()装饰器。

@Component({
  selector: 'single-component',
  template: `
  <button (click)="liked()">Like it?</button>
  `
})
class SingleComponent {
  @Output() putRingOnIt: EventEmitter<string>;

  constructor() {
    this.putRingOnIt = new EventEmitter();
  }

  liked(): void {
    this.putRingOnIt.emit("oh oh oh");
  }
}

例子中的子组件需要完成三步操作,指定输出属性(使用@output()标注);创建EventEmitter对象并绑定到对应输出属性;当特定方法(比如liked())被调用时发出事件。

@Component({
  selector: 'club',
  template: `
  <div>
  <single-component
  (putRingOnIt)="ringWasPlaced($event)"
  ></single-component>
  </div>
  `
})
class ClubComponent {
  ringWasPlaced(message: string) {
    console.log(`Put your hands up: ${message}`);
  }
}

父组件中$event包含了由子组件传回的数据。