摘要:我们使用了模式书写,并引入了思想,这些以前只在里见到的设计,现在里也有体现,并且在本章中会着重讲解多的协作。如果之前写过,那对于这种书写方式一定无比熟悉。每次数据的变更,无论是还是,都将变化冒泡到,然后由再向下逐级推送各组件是否重绘。
前集回顾
在上一章里我们讲了如何在angular2下开发一个component(还没做的赶紧去学吧)。我们使用了Unidirectional Data Flow模式书写component,并引入了Immutable思想,这些以前只在React里见到的设计,现在angular2里也有体现,并且在本章中会着重讲解多components的协作。
本章源码:multicomponents
本章使用angular2版本为:2.4.5,webpack版本为: 2.2.0
先来看看我们将要完成的效果图:
需求分析(注意动画部分),由上一章的一个component,变成了一个输入component、 一个遍历显示component、 一个总结component。画一个组件树的示意图如下:
图片描述
分析第一部分我们将其命名为InputItem
它由一个input[type="text"]和一个button组成
当点击button时,需要向上冒泡事件,并组合一个新的CheckableItem随事件发送出去
清空input[type="text"]
第3步操作,也可以通过键盘敲击"回车键"完成操作
分析第二个遍历显示部分参考上一章
关于*ngFor
我们将其命名为Counter
它由一个span组成,显示总结信息
它接受一个items参数,用来生成总结信息
总结信息为:显示当前还有多少个isChecked === false的item
设计use case还是老套路,先来设计这些新的components的使用场景(这种方式,我们称之为"BDD",不了解的朋友参考以BDD手写依赖注入。
重构ts/app.tsimport {Component} from "@angular/core"; import {Item} from "./CheckableItem"; @Component({ selector: "my-app", template: `实现InputItemMy First Angular 2 App
` }) 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) ]; } }
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: `` }) 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: `
We have {{ length }} item{{ postFix }}
`
})
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: `` }) 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
你又看到了伟大的效果:
下回预告:使用service
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/79219.html
摘要:通过增加删除元素改变布局的。譬如和控制元素显示隐藏,或者改变元素行为的。譬如设计看过我之前介绍以手写依赖注入的朋友应该已经对行为驱动多少有些了解了。她有,并且包含了至少一个和一个标签。,将左边的事件传递给了右边的表达式通常就是事件处理函数。 前集回顾 在上一章里我们讲了如何为angular2搭建开发环境(还没搭起来的赶紧去看哦),并使之跑起来我们的第一个My First Angular...
摘要:前集回顾上一章里我们在里通过组合三个组件,并通过单向数据流的方式把她们驱动起来。设计每章都会提一下,先设计使用场景这种方式,我们称之为,不了解的朋友参考以手写依赖注入。 前集回顾 上一章里我们在AppComponent里通过组合InputItem、 CheckableItem、 Counter三个组件,并通过Unidirectional Data Flow(单向数据流)的方式把她们驱动...
angular2是什么?我猜不容我赘述,各位一定略有耳闻,无论是曾经AngularJS的拥趸,亦或是React的粉丝,都或多或少的对她有过一点了解。未见其物、先闻其声,angular2在问世之前已经做足了宣传,想必诸位也一定被下面各种词汇所震慑,什么:TypeScript、 ES5、 ES6、 Dart、 Immutable、 Unidirectional Data Flow、 Reactive ...
摘要:可以在不必打断其它业务的前提下,升级应用程序,因为这项工作可以多人协作完成,在一段时间内逐渐铺开,下面就方案展开说明主要依赖提供模块。在混合式应用中,我们同时运行了两个版本的。这意味着我们至少需要和各提供一个模块。 angular1.x 升级 angular2+ 方案 我给大家提供的是angular1.x和angular5并行,增量式升级方案,这样大家可以循序渐进升级自己的应用,不想看...
摘要:的思想非常先进,摒弃了那种复杂的构建模式,采用了组件化开方的方,那我们一起来看一看,一个基础的组件是什么样子的呢。 angular2的思想非常先进,摒弃了angular1那种复杂的构建模式,采用了组件化开方的方,那我们一起来看一看,一个基础的组件是什么样子的呢。angular2-demoshowImg(http://static.xiaomo.info/images/angular.p...
阅读 964·2023-04-26 02:56
阅读 9437·2021-11-23 09:51
阅读 1849·2021-09-26 10:14
阅读 2979·2019-08-29 13:09
阅读 2153·2019-08-26 13:29
阅读 570·2019-08-26 12:02
阅读 3561·2019-08-26 10:42
阅读 2999·2019-08-23 18:18