angular2初入视线之-多components合作

前集回忆

上一章里我们讲了如安在angular2下开辟一个component(还没做的赶忙去学吧)。我们运用了Unidirectional Data Flow形式誊写component,并引入了Immutable头脑,这些之前只在React里见到的设想,如今angular2里也有表现,并且在本章中会偏重解说多components的合作。

本章源码:multicomponents

本章运用angular2版本为:2.4.5webpack版本为: 2.2.0

先来看看我们将要完成的结果图:

《angular2初入视线之-多components合作》

需求剖析

(注重动画部份),由上一章的一个component,变成了一个输入component、 一个遍历显现component、 一个总结component。画一个组件树的示意图以下:

图片形貌

剖析第一部份

  1. 我们将其命名为InputItem

  2. 它由一个input[type="text"]和一个button构成

  3. 当点击button时,须要向上冒泡事宜,并组合一个新的CheckableItem随事宜发送出去

  4. 清空input[type="text"]

  5. 第3步操纵,也能够经由过程键盘敲击”回车键”完成操纵

剖析第二个遍历显现部份

参考上一章
关于*ngFor

剖析第三个总结部份

  1. 我们将其命名为Counter

  2. 它由一个span构成,显现总结信息

  3. 它接收一个items参数,用来天生总结信息

  4. 总结信息为:显现当前另有多少个isChecked === falseitem

设想use case

照样老套路,先来设想这些新的components的运用场景(这类体式格局,我们称之为”BDD”,不相识的朋侪参考以BDD手写依靠注入

重构ts/app.ts

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

import {Item} from './CheckableItem';

@Component({
    selector: 'my-app',
    template: `
    <h1>My First Angular 2 App</h1>
    <!--
        在template里,增添input-item和counter的运用
        input-item里,捕捉onItemAdded事宜,传递给addItem要领
    -->
    <input-item (onItemAdded)="addItem($event)"></input-item>
    <!--
        运用*ngFor遍历items变量。概况:
        https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngFor
    -->
    <checkable-item *ngFor="let itemInfo of items; let i = index" [item]="itemInfo" (onItemClicked)="toggle($event, i)">
    </checkable-item>
    <!--
        counter里,传入items
    -->
    <counter [items]="items"></counter>
    `
})
export class AppComponent {
    //声明items为成员变量
    items: Item[] = [];

    //当捕捉到onItemAdded事宜时,挪用该要领,增加新item到items里
    //注:依据Immutable战略,天生新的items
    addItem(item: Item) {
        this.items = [...this.items, item];
    }

    //点击checkable-item时,置反其isChecked属性
    //注:依据Immutable战略,天生新的items
    toggle(item: Item, index: number) {
        this.items = [
            ...this.items.slice(0, index),
            { isChecked: !item.isChecked, txt: item.txt },
            ...this.items.slice(index + 1)
        ];
    }
}

完成InputItem

touch ts/InputItem.ts

向刚建立的ts/InputItem.ts中,增加以下内容:

import {Component, Output, EventEmitter, ChangeDetectionStrategy} from '@angular/core';

@Component({
    //这里依然运用OnPush战略
    changeDetection: ChangeDetectionStrategy.OnPush,
    selector: 'input-item',
    //template里包括一个input[type="text"]和button
    //表面又一个form标签是因为需求中愿望回车键也能够触发操纵
    template: `
    <form (ngSubmit)="onSubmit()">
        <input type="text" [(ngModel)]="text" name="todo">
        <button type="submit">Add Item</button>
    </form>
    `
})
export class InputItem {
    //双向绑定到input[type="text"]
    text: string;
    //向外部冒泡的事宜
    @Output() onItemAdded = new EventEmitter();

    //不管点击button、照样敲击回车键,都处分增加事宜
    //组装一个新的item对象,
    //清空text
    onSubmit() {
        this.onItemAdded.emit({
            isChecked: false,
            txt: this.text
        });
        this.text = '';
    }
}

完成Counter

touch ts/Counter.ts

向刚建立的ts/Counter.ts中,增加以下内容:

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

import {Item} from './CheckableItem';

@Component({
    //这里依然运用OnPush战略
    changeDetection: ChangeDetectionStrategy.OnPush,
    selector: 'counter',
    //template包括一个span
    template: `
    <span>
        We have {{ length }} item{{ postFix }}
    </span>
    `
})
export class Counter implements OnChanges {
    //接收items参数
    @Input() items: Item[];

    postFix: string;
    length: number;

    //每次当参数items的reference发生变化时,触发该要领
    //猎取新的length、postFix,重绘组件
    //这里和React中的componentWillUpdate很类似
    ngOnChanges(changes: { [key: string]: SimpleChange }): any {
        let newItems: Item[] = changes['items'].currentValue;
        this.length = newItems.reduce((p, item) => p + (item.isChecked ? 0 : 1), 0);
        this.postFix = this.length > 1 ? 's' : '';
    }
}

修正CheckableItem

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

@Component({
    changeDetection: ChangeDetectionStrategy.OnPush,
    selector: 'checkable-item',
    styles: [`
        .deleted{
            text-decoration: line-through;
        }
    `],
    template: `
    <div>
        <input type="checkbox" [checked]="item.isChecked" (change)="clickItem($event)">
        <label [class.deleted]="item.isChecked">{{ item.txt }}</label>
    </div>
    `
})
export class CheckableItem {
    @Input() item: Item;
    @Output() onItemClicked = new EventEmitter();

    clickItem(e: MouseEvent) {
        e.preventDefault();
        this.onItemClicked.emit(this.item);
    }
}


export interface ToggleItemHandler {
    (item: Item): void;
}

export interface Item {
    isChecked?: boolean;
    txt?: string;
}

组件树的团体编写思绪就是Unidirectional Data Flow,所以数据的变动都是Immutable的。假如之前写过React,那关于这类誊写体式格局肯定非常熟习。每次数据的变动,不管是InputItem照样CheckableItem,都将变化冒泡到AppComponent,然后由AppComponent再向下逐级推送各组件是不是重绘。

引入声明

翻开index.ts,增添新模块声明引入

import 'core-js/es6';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule }   from '@angular/forms';
import { AppComponent }  from './app';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import {CheckableItem} from './CheckableItem';
import {InputItem} from './InputItem';
import {Counter} from './Counter';

@NgModule({
  imports:      [ BrowserModule, FormsModule ],
  declarations: [ AppComponent, CheckableItem, InputItem, Counter ],
  bootstrap:    [ AppComponent ]
})
class AppModule { }

platformBrowserDynamic().bootstrapModule(AppModule);

OK,代码写到这里基本就完毕了,看看结果吧

npm start

你又看到了巨大的结果:

《angular2初入视线之-多components合作》

下回预报:运用service

    原文作者:leftstick
    原文地址: https://segmentfault.com/a/1190000004961316
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞