截止到目前为止,Angular2.0完成了其alpha-32版本的开发,新的版本还在迭代开发当中,这其中有个问题,就是每个版本相比于以前的版本都会有一些改动,包括API方面的修改,这会导致很多基于以前版本写的demo都无法运行,而且其官网上给出的教程也是基于之前的版本而没有及时更改,这就造成了即使按照官网的教程去编写运行也可能得到不预期的结果,针对这种情况,本文采用最新的较稳定的Angular alpha-31版本重构其官网上的step by step guide,并以此为基点,介绍Angular2中的组件(components).

组件(Components)是在软件开发过程中的一种发展趋势,它基于封装技术,着力于减少软件模块开发中的耦合度,在传统的后端语言开发中早已经得到了很好的实现和发展,比如微软的com组件。在web开发中,截止到目前为止,还没有一种能够得到浏览器原生支持并且广泛使用的组件技术。目前W3C制定出了web components规范,Shadow DOM作为实现该规范的一种关键技术也是在不断的发展中。可惜的是目前浏览器支持度并不好,离实际广泛使用还存在很长的一段距离。所以在目前比较著名的解决方案是谷歌的polymer和Mozilla的X-TAG,它们允许在一部分现代浏览器上能够封装自定义用户组件,并且让该组件独立于客户端js之外,即不能够通过客户端js去修改或者操作该组件内部元素,自定义组件对外表现为一个整体。这就好比html5的video 标签,你只需要在页面上放置一个video标签,它就能够被浏览器渲染成一个播放的画面以及播放控制条,即使你在开发者工具中查看原码,也能够看到一个video标签而不能够看到它内部的实现。外部js只能够通过有限的API去控制它的行为,而且不管该页面本来样式有何不同,它在不同页面上渲染出来的效果都是相同的。这就是web 组件化。

Angular2.0也正是按照这一思路来设计整个框架的,可以说Angular2.0中,组件是它的核心概念。前面讲到,由于浏览器目前还不能够提供对web Components的原生支持,所以Angular从框架的角度来视图解决这一问题。本文的目的就是讲解如何在Angular2.0中实现一个组件。

为了便于快速演示效果,免去环境搭建的过程,我在github上传了一个种子项目,用于以后对Angular2.0的学习。本文基于这个项目,一步步去了解组件的概念。

步骤一,克隆种子项目到本地

在本地创建一个文件夹,在该文件夹中进行git clone操作

git clone https://github.com/myzhibie/ng2-demo.git

第二步,本地全局安装gulp(如果已经安装,可以省去这一步)

npm install -g gulp

第三步,在项目根目录下安装项目的所有依赖项

npm install

这一步可能需要翻墙,如果失败一般都是网络原因。

如果上述步骤都成功,那么到此为止,已经可以运行该种子项目了

gulp play

在原始的种子项目中,src文件夹下已经有了本文的所有代码作为参考,可以将它们完全(除了index.html和style.css)删除然后自己创建。

1.创建一个简单的组件

在src文件夹下创建一个display.js文件(严格来讲是ts文件,因为本文是采用typescript脚本来构架的,当然你也可以使用ES5,ES6来编写整个项目,但是相比于typescript较为复杂,Angular2官方的教程中,也是采用首选typescript脚本,目测随着Angular2的推动,微软的typescript会火啊),用来编写组件的逻辑,并在html中采用如下代码引用它

System.import('display');

在index.html中,添加一行html代码

<display></display>

这表示自定义了一个display组件。

然后转到display.js中,编写逻辑如下

 import {ComponentAnnotation as Component, ViewAnnotation as View, bootstrap,NgFor,NgIf} from 'angular2/angular2';

 class FriendService {
names:Array<string>;
constructor(){
this.names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
}
}
@Component({
selector: 'display',
hostInjector:[ FriendService ]
})
@View({
templateUrl: 'showData.html',
directives:[NgFor,NgIf]
})
class DisplayComponent {
myName: string;
names:Array<string>;
constructor(friendService:FriendService) {
this.myName='myzhibie';
this.names=friendService.names;
}
updateItems(name:string){
this.names.push(name);
}
doneTyping($event){
if($event.which===13){
this.updateItems($event.target.value);
$event.target.value=null;
}
}
} bootstrap(DisplayComponent);

代码第一行首先引入了component,view,bootstrap,以及ngFor,ngIf几个核心的指令,第3到8行定义了一个外部的service,类似于Angular1.X中的service,可以将一些公用的方法或者代码抽象为一个service,然后采用注入的方式在Component中进行调用,从思想上来讲,这和Angular1.X没有任何区别,但是具体的定义方式发生了较大变化,Angular2中就是使用class关键字来定义,结构很清晰。这个service拥有一个names属性是字符串数组类型,并在构造函数中对它进行了初始化。代码9到12行定义了该组件相关的配置项,selector属性是一个选择器,用于选择该组件对应于html页面上的哪个DOM元素。hostInjector属性表示将FriendService注入到了这个组件当中,这行代码是保证能够在Angular2 alpha31版本运行的依赖注入的方式,官网上给出的是appInjector,那个是之前的版本的DI的配置属性。

代码13-16行定义了该组件view相关的配置,templateUrl代表其对应的模板文件,是showData.html.directives表示在其模板中可以使用的内置指令,这里我们选择ngFor和ngIf,前者用来循环,后者用来进行判断,具体用法在showData.html中会给出。

代码第17到33行就是定义了一个完整的组件,你会发现就是一个class,而不是Angular1.X中那种controller的形式,实际上,这个组件的class就是它的Controller,这种定义方式更优雅简洁一些。20-23行是这个组件的构造函数,用来初始化它的属性,其中names属性是通过依赖注入的friendService对象来的。同时在该controller种定义了两个方法,updateItems用来添加新的names项,doneTyping方法用来处理组件中的input标签在完成输入后按回车键去添加names项的操作。下面是showData.html的内容

 <p>friends:</p>
<ul>
<li *ng-for="#name of names">
{{ name }}
</li>
</ul>
<input #nametext (keyup)="doneTyping($event)">
<button (click)="updateItems(nametext.value)" >addItems</button>
<p class="p2" *ng-if="names.length > 3">you have many friends</p>

第3到6行是一个ul里面加入了li,通过ng-for指令循环(类似于1中的ng-repeat)其controller中的names属性,注意调用指令的时候前面要加上*表示这是一个Angular2的内置指令,同时使用#来定义在循环中的一个局部变量,第4行使用{{}}来绑定变量。第7行是一个input 标签,该标签中定义了一个nametext局部变量,可以在该页面的其他地方引用。需要注意的是,你不能定义成nameText或者name-text,这两种方式在Angular2中会被转化,得不到确定的结果,相信这个问题在随后的正式发布中会得到解决。同时,给input标签注册一个onkeyup事件,让它指向其controller中的doneTyping方法,并且它的参数$event代表event对象。第8行给button标签注册一个onclick事件,它的参数通过局部变量nametext来引用上面input标签的值。第9行在p标签中采用ng-if指定,如果其controller的names长度大于3就显示这个p标签,否则不显示。

运行以上代码,结果如下:

可以通过在input中写入值点击按钮添加li,也可以通过回车键添加。

2.组件之间的引用

通过上面的练习,我们知道了如何定义一个组件并为它绑定事件来响应用户请求,实际上就是定义一个完整的组件,但是web引用并不是一个组件就能够搞定的,Angular2.0允许你以更简单的方式在自定义组件中引用其他组件,也就是组件之间的引用。

首先的index.html中添加一行代码

<parent></parent>

表示这是一个parent组件,然后添加一个parent.js文件,编写逻辑如下:

 import {ComponentAnnotation as Component, ViewAnnotation as View, bootstrap,NgFor,NgIf} from 'angular2/angular2';

 @Component({
selector:'parent'
}) @View({
template:'<h1 class="hparent">{{message}}</h1><child></child>',
directives:[ChildComponent]
})
class ParentComponent {
message:string;
constructor(){
this.message='parent component';
}
} @Component ({
selector:'child'
}) @View({
template:'<p class="pchild">{{ message }}</p>'
}) class ChildComponent{
message:string;
constructor(){
this.message='child component';
}
}
bootstrap(ParentComponent);

代码第3到16行用于定义父组件,第18到31行定义了一个子组件ChildComponent,需要注意的是第8-9行,组件之间的引用是在view注解中template中插入组件的占位符<child></child>,然后在directives中引用它的class名称。这就完成了组件的调用,通过这种方式,可以采用“堆积木”的方法来构建我们的web应用,同时它提高了代码的复用率。运行结果如下:

审查元素结果如下:

从上面可以看出,Angular2.0对于组件的定义和使用相对于Angular1.x是更为简单和优雅的,学习曲线较Angular1.X平坦一些。

原码地址https://github.com/myzhibie/ng2-demo

Angular2.0-组件的更多相关文章

  1. angular2.0学习笔记1.开发环境搭建 (node.js和npm的安装)

    开发环境, 1.安装Node.js®和npm, node 6.9.x 和 npm 3.x.x 以上的版本. 更老的版本可能会出现错误,更新的版本则没问题. 控制台窗口中运行命令 node -v 和 n ...

  2. Webstorm 下的Angular2.0开发之路

    人一旦上了年纪,记忆力就变得越来越不好. 最近写了许多的博文,倒不是为了给谁看,而是方便自己来搜索,不然一下子又忘记了. 如果恰巧帮助到了你,也是我的荣幸~~~~~~~~~~~~ 废话不多说,看正题~ ...

  3. Angular2.0的项目架构

    Angular2.0的项目架构 一.项目服务端app a) Controller控制器 b) Router路由 c) Service服务 d) Public公共样式及脚本和图片等静态资源 e) Vie ...

  4. Vue2.0组件间数据传递

    Vue1.0组件间传递 使用$on()监听事件: 使用$emit()在它上面触发事件: 使用$dispatch()派发事件,事件沿着父链冒泡: 使用$broadcast()广播事件,事件向下传导给所有 ...

  5. Angular2.0快速开始

    参考资料: Angular2.0快速开始 AngularJS2 教程

  6. 通信vue2.0组件

    vue2.0组件通信各种情况总结与实例分析   Props在vue组件中各种角色总结 在Vue中组件是实现模块化开发的主要内容,而组件的通信更是vue数据驱动的灵魂,现就四种主要情况总结如下: 使用p ...

  7. WINCE6.0组件选择说明

    WINCE6.0组件选择说明 图1 RAS/PPP组件前面的√标识表示我们手动选择,TAPI2.0前面的■标识表示选组件时根据依赖关系自动选择的,PPPoE前面的□标识组件没有选择.

  8. ASP.NET2.0组件控件开发视频 初体验

    原文:ASP.NET2.0组件控件开发视频 初体验 ASP.NET2.0组件控件开发视频 初体验 录了视频,质量不是很好,大家体验下.我会重新录制的 如果不清楚,可以看看http://v.youku. ...

  9. vue2.0组件传值

    props down   emit up 嘿嘿    如果是第一次接触vue2.0组件传值的肯定很疑惑,这是什么意思(大神总结的,我也就是拿来用用) “down”—>指的是下的意思,即父组件向子 ...

  10. angular2.0学习笔记4.npm常用指令记录及angular语法

    以下命令,都需要在命令行窗口中,先切入到项目文件夹目录,再执行 1.npm start 这个命令会在“监听”模式下运行TypeScript编译器,当代码变化时,它会自动重新编译. 同时,该命令还会在浏 ...

随机推荐

  1. node.js基础 1之简单的nodejs模块

    模块流程: 创建模块->导出模块->加载模块->使用模块 ndoejs主要就是把项目变成模块化在管理 实现一个模块的调用,编写student.js.teacher.js.klass. ...

  2. MPICH3 配置安装问题列表

    问题列表 1: configure: error: F90 and F90FLAGS are replaced by FC and FCFLAGS respectively in this confi ...

  3. vue学习笔记之v-if

    if顾名思义就是判断,v-if也是判断,举例如下 <p v-if="hello">Hello!</p> 这里 v-if 指令将根据表达式 hello 值的真 ...

  4. python--安装PIL

    PIL:Python Imaging Library,已经是Python平台事实上的图像处理标准库了.PIL功能非常强大,但API却非常简单易用. 安装PIL 在Debian/Ubuntu Linux ...

  5. CEF使用的几个注意点

    CEF为chrome浏览器的切入其他浏览器中的轻量级框架. 开发的客户端的时候,这是作为界面显示的首先,可以增强客户的易变性,可塑性. 在开发的过程中(侧重于C,C++解决),遇到的几个问题,以及自己 ...

  6. ABAP之PINYING拼音

    前面说了声母韵母,那么现在来说说ABAP里的拼音——域,数据元素,结构 PINGGUO = 苹果 T-CODE : SE11   如下图 域:是一些特定值的集合,或者某一种特殊用途的集合.如:需要定义 ...

  7. iOS开发UI篇—在UIImageView中添加按钮以及Tag的参数说明

    ios开发UI篇—在ImageView中添加按钮以及Tag的参数说明 一.tag参数 一个视图通常都只有一个父视图,多个子视图,在开发中可以通过使用子视图的tag来取出对应的子视图.方法为Viewwi ...

  8. 用maven搭建 testNG+PowerMock+Mockito测试框架

    单元测试是开发中必不可少的一部分,是产品代码的重要保证. Junit和testNG是当前最流行的测试框架,Junit是使用最广泛的测试框架,有兴趣的话自己baidu一下. testNG基于Junit和 ...

  9. spirng定时任务的两种配置:注解和xml

    一 使用注解Task 1.在applicationContext.xml中配置 <?xml version="1.0" encoding="UTF-8"? ...

  10. Service中事务不能回滚的解决方式(转)

    1.在service方法里面如果对异常进行了捕获的话,该事务是不会进行回滚的        默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚.          spr ...