摘要:通过增加删除元素改变布局的。譬如和控制元素显示隐藏,或者改变元素行为的。譬如设计看过我之前介绍以手写依赖注入的朋友应该已经对行为驱动多少有些了解了。她有,并且包含了至少一个和一个标签。,将左边的事件传递给了右边的表达式通常就是事件处理函数。
前集回顾
在上一章里我们讲了如何为angular2搭建开发环境(还没搭起来的赶紧去看哦),并使之跑起来我们的第一个"My First Angular 2 App"。当然也有不少朋友反映环境搭建似乎比较复杂,整整一篇教程,最后只简单输出了一句话!这里我要说一句,学习新知识的确有一个阵痛的过程,尤其像angular2这种框架,引入了大量以前"前端"并不关心(没有需求)的技术栈,这使得对于之前没有接触过这些概念的朋友的学习曲线陡然飙升,相信不少人看了上一章里开篇时的那些名词后已经认识到这一点了!本教程主打实际操作,但也不会完全忽略理论,我们边做边理解。今天就接着上一章的余温,我们来写一个简单component。
本章源码:component
本章使用angular2版本为:2.4.5, webpack版本为: 2.2.0
先来看看我们将要完成的效果图:
(注意动画的部分)非常简单的一个component,有木有?那好,我们现在要做的就是为这样一个component描述需求:
她要能接受一个object用来描述初始值,如:isChecked(是否选中)、 txt(显示文本)
当选中时,需要有横线覆盖文本;反之亦然
当用户点击复选框时,需要向上广播该事件,由父组件(调用方)决定点击时该做什么。这里我们需要在父组件里改变component的isChecked状态,并使component重绘
她必须是一个处理Unidirectional Data Flow(单向数据流)的component,意思是传入参数必须不可变(Immutable)
注:第4步里,我们使用Unidirectional Data Flow模型来更新数据,并没有涉及到任何Reactive Programming的知识点
为了完成以上需求,我们需要了解下面知识点
什么是component或者这么问,AngularJS里有directive;angular2里有component,他们是什么关系?该如何理解angular2里的component?原谅我这里就不再详述AngularJS里的directive了,直接介绍component:
Component: 简单说,就是带template的directive,也是最常见的组件形式。譬如:上一章中,ts/app.ts里的AppComponent。
Structural directive: 通过增加/删除DOM元素改变DOM布局的directive。譬如:NgFor和NgIf
Attribute directive: 控制DOM元素显示/隐藏,或者改变元素行为的directive。譬如:NgStyle
设计use case看过我之前介绍以BDD手写依赖注入(dependency injection)的朋友应该已经对"行为驱动"多少有些了解了。当我们需要设计一个API或者组件时,最佳的方式就是先设计她的使用场景,从行为开始,对该API或者组件进行描述,最后再将缺失的“实现”部分补全就可以了。
假设我们将在上一章中的AppComponent里使用这个新的component,根据之前的需求描述,我们的使用场景应该是这个样子的 :
import {Component, OnInit} from "@angular/core"; import {Item} from "./CheckableItem"; //该component使用checkable-item作为selector //并可以通过[item]属性传入一个object //还可以通过(onItemClicked)接受一个点击事件 @Component({ selector: "my-app", template: `实现componentMy First Angular 2 App
` }) export class AppComponent implements OnInit { itemInfo: Item; //当实现OnInit接口时,必须重写ngOnInit方法 //关于OnInit,详见: //https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#hooks-overview ngOnInit() { //设定初始值 //根据需求第1条,包含两个属性 this.itemInfo = { isChecked: false, txt: "Hello World!" }; } //根据需求第3条,点击component后,事件要 //冒泡到父组件(调用方) toggle(item: Item) { //当获取到CheckableItem的点击事件时, //给itemInfo重新赋值,并将isChecked置反 //注:重新赋值是根据需求第4条的不可变性 this.itemInfo = { isChecked: !item.isChecked, txt: item.txt }; } }
根据上述介绍,再结合之前的效果图,我们要做的当然就是一个标准的Component。她有template,并且包含了至少一个input和一个label标签。
有了使用场景(行为),接下来就是实现这个CheckableItem了:
touch ts/CheckableItem.ts
向刚创建的ts/CheckableItem.ts文件里写入如下内容:
import {Component, Input, Output, EventEmitter, ChangeDetectionStrategy} from "@angular/core"; @Component({ //脏检查策略,OnPush指当且仅当传入参数的reference发生变更时 //触发组件重绘。这和React中的shouldComponentUpdate异曲同工, //不过更先进(因为React还是需要手动实现的) //这也是上一步里itemInfo必须重新赋值的原因 changeDetection: ChangeDetectionStrategy.OnPush, selector: "checkable-item", //仅在当前component作用域下有效的class styles: [` .deleted{ text-decoration: line-through; } `], //template就如我们需求里的描述那样,由一个input标签和 //一个label标签组成 template: `` }) export class CheckableItem { //item被声明为Input,即会在父组件传入参数时用到 @Input() item: Item; //onItemClicked被声明为Output,用来在用户点击input标签 //时向上冒泡事件 @Output() onItemClicked = new EventEmitter(); //监听input上的click事件,当用户点击时,首先阻止默认行为 //因为是否变化(重绘)是由父组件决定的 //然后冒泡点击事件 clickItem(e: MouseEvent) { e.preventDefault(); this.onItemClicked.emit(this.item); } } export interface ToggleItemHandler { (item: Item): void; } export interface Item { isChecked?: boolean; txt?: string; }
有朋友看到这里,对[]、 ()之类的绑定标签表示不解,这里我们统一来解释:
[target] = "expression",将右边表达式对应的值绑定到左边的target。譬如:在ts/app.ts里,我们使用[item]="itemInfo"将itemInfo对应的值绑定到了组件CheckableItem的item上,这样,在CheckableItem里就可以通过this.item获取到父组件传进来的参数了。
(target) = "statement",将左边的事件传递给了右边的表达式(通常就是事件处理函数)。譬如:在ts/app.ts里,我们使用(onItemClicked)="toggle($event)"将CheckableItem冒泡上来的onItemClicked事件传递给了toggle函数。
[class.deleted]="item.isChecked",是class的一种特殊用法,指当item.isChecked表达式为真时,为该标签的class里增加deleted;反之,则删除该标签class里的deleted
引入声明打开之前写的index.ts,增加CheckableItem引入:
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 { AppComponent } from "./app"; import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"; //引入CheckableItem import {CheckableItem} from "./CheckableItem"; @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent, CheckableItem ],//引入声明 bootstrap: [ AppComponent ] }) class AppModule { } platformBrowserDynamic().bootstrapModule(AppModule);见证奇迹
OK,事已至此,我们是不是又该启动一把程序看看效果了?
npm start
你又看到了伟大的效果:
下回预告:小刀升级 - 多component协作
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/79203.html
摘要:前集回顾上一章里我们在里通过组合三个组件,并通过单向数据流的方式把她们驱动起来。设计每章都会提一下,先设计使用场景这种方式,我们称之为,不了解的朋友参考以手写依赖注入。 前集回顾 上一章里我们在AppComponent里通过组合InputItem、 CheckableItem、 Counter三个组件,并通过Unidirectional Data Flow(单向数据流)的方式把她们驱动...
摘要:我们使用了模式书写,并引入了思想,这些以前只在里见到的设计,现在里也有体现,并且在本章中会着重讲解多的协作。如果之前写过,那对于这种书写方式一定无比熟悉。每次数据的变更,无论是还是,都将变化冒泡到,然后由再向下逐级推送各组件是否重绘。 前集回顾 在上一章里我们讲了如何在angular2下开发一个component(还没做的赶紧去学吧)。我们使用了Unidirectional Data ...
angular2是什么?我猜不容我赘述,各位一定略有耳闻,无论是曾经AngularJS的拥趸,亦或是React的粉丝,都或多或少的对她有过一点了解。未见其物、先闻其声,angular2在问世之前已经做足了宣传,想必诸位也一定被下面各种词汇所震慑,什么:TypeScript、 ES5、 ES6、 Dart、 Immutable、 Unidirectional Data Flow、 Reactive ...
摘要:为了简单起见,在本文中将会使用。已经实例化了并且将它的模板载入到了元素中。中的依赖注入发生在该类的构造函数中,因此我们将在构造函数中注入。 国内 Angular2 资料比较少,这里看到一篇不错的入门文章就分享过来了 —— Angular 2 快速上手,这里面还有很多有关于 Angular2 的文章,感兴趣的朋友可以去看一看 目前angular2已经来到了beta版,这意味着它已经做好了...
摘要:的思想非常先进,摒弃了那种复杂的构建模式,采用了组件化开方的方,那我们一起来看一看,一个基础的组件是什么样子的呢。 angular2的思想非常先进,摒弃了angular1那种复杂的构建模式,采用了组件化开方的方,那我们一起来看一看,一个基础的组件是什么样子的呢。angular2-demoshowImg(http://static.xiaomo.info/images/angular.p...
阅读 1086·2021-10-08 10:04
阅读 3525·2021-08-05 10:01
阅读 2281·2019-08-30 11:04
阅读 1799·2019-08-29 15:29
阅读 843·2019-08-29 15:12
阅读 1672·2019-08-26 12:11
阅读 3118·2019-08-26 11:33
阅读 1164·2019-08-26 10:23