前言:css
本系列在前面两篇文章,介绍了Zone.js和angular2的基础概念。然后对于ng2的学习,仍是由官方的 Tour of Heroes 开始。html
如下内容通过提炼和我的理解,固然也会有不正确的地方,欢迎指正。有兴趣的朋友,能够本身开始ng2之旅,再结合本篇文章一块儿理解。git
ng2的配置比较麻烦,任意的引入包可能致使一些报错,建议直接官方下载 quickStart 。github
ng2 将全部api分红7个类型,在查阅api的时候,能够多留意一下他们的类型,便于理解bootstrap
@Componentapi
@Component 申明一个应用程序可重用的UI组件,能够经过bootstrap实例化,也能够经过它自己directives属性相互实例化调用。浏览器
/* app.component.ts */ import {Component} from '@angular/core'; @Component({ selector: 'app-component', template: `<div>{{title}}</div>` }) export class AppComponent{ title = 'Tour of Heroes'; }
/* main.ts */ import {bootstrap} from '@angular/platform-browser-dynamic' import {AppComponent} from './app.component' bootstrap(AppComponent)
//index.html <body> <app-component></app-component> </body> /* 最终页面渲染 */ <body> <app-component> <div>Tour of Heroes </div> </app-component> </body>
@Component 会为组件建立一个shadow DOM,将选中的模板加载到shadow DOM,建立全部配置的注入对象。angular2
bootstrap 引导运行@Component时,会先根据@Component 的selector找到dom,并新建一个子注射器,经过一个新Zone实例进行变化检测,app
建立一个shadow DOM并载入到dom节点汇总,实例化组件,最后初始化提供的数据。dom
shadow dom:
在ng2的文档里,说起了shadow dom。能够参考文章:Shadow DOM:基础。
shadow dom能让dom和css样式作到有做用域划分,能够相互独立,样式不相互影响。
而浏览器对shadow dom的支持并很差,可是ng2用其余方式,实现了相似shadow dom的功能。
好比,当@Component配置了styles属性,在组件实例化的时候,style会被载入到head
如上图,实际咱们的style本来写的是h1选择器,ng在后面加上了属性选择器[_ngcontent-hvh-1]。
在组件的根dom,ng也会加上[_ngcontent-hvh-1]此属性。
经过一个属性选择器,ng2自动为咱们隔离了style的做用域。
每一个组件都将会加入一个特定的属性,属性后面的数字按照载入顺序累加: [_ngcontent-hvh-1] -> [_ngcontent-hvh-2] ......
@Input&@Output:
使用@input绑定标签属性,建立组件通讯的单向输入流。须要引入组件:import { Input } from '@angular/core';
“英雄之旅”例子:
/* A */ import { Input } from '@angular/core'; @Component({ selector: 'bank-account', template: ` Bank Name: {{bankName}} Account Id: {{id}} ` }) class BankAccount { @Input() bankName: string; @Input('account-id') id: string; // this property is not bound, and won't be automatically updated by Angular normalizedBankName: string; } /* B */ @Component({ selector: 'app', template: ` <bank-account bank-name="RBC" account-id="4747"></bank-account> `, directives: [BankAccount] }) class App {} bootstrap(App);
在一个指令组件的类里使用@Input() 对一个变量进行申明,被申明的变量能够经过指令的属性进行单向数据绑定。
@Input 有一个参数,绑定dom的属性名,如上面代码: @Input('account-id') id: string;
dom属性名account-id和类的id变量进行了绑定,<bank-account account-id="4747">
未带参数的属性名默认用变量名 @Input() bankName: string; <bank-account bank-name="RBC">
这样就实现组件之间的通讯和绑定了。
在angular1中,directive中定义属性scope,达到scope做用域之间的数据绑定,和angular2中的@Input功能相似
scope : { bankName : "=", accountId : "=" }
<directive bank-name="RBC" account-id="4747"></directive>
@Output和@Input相反
OnInit&constructor
constructor执行在ngOnInit以前。但他们的概念不一样。OnInit和 constructor都能实现初始化时候执行,
import {OnInit} from '@angular/core'; export class AppComponent implements OnInit{ constructor(){ //do something } ngOnInit(){ //do something } }
route:
RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS 。配置路由,须要引入
import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated'; @Component({ selector: 'my-app', template: ` <h1>{{title}}</h1> <a [routerLink]="['Heroes']">Heroes</a> <router-outlet></router-outlet> `, directives: [ROUTER_DIRECTIVES], providers: [ ROUTER_PROVIDERS, HeroService ] }) @RouteConfig([ { path: '/heroes', name: 'Heroes', component: HeroesComponent } ])
[routerLink]用于指定载入连接,会对应 @RouteConfig 的 name 属性,
找到 name 以后修改路由,并显示相应UI组件,最终载入到<router-outlet>标签下。
使用router-outlet,UI组件将会本身建立selector标签,将组件加载到router-outlet标签下。
默认路由&路由传参:
@RouteConfig([ { path: '/detail/:id',//能够经过此方式传参 name: 'HeroDetail', component: ComponentA, useAsDefault: true //设置默认路由,错误访问地址都将访问默认路由 } ])
如上代码:ComponentA 要接收参数,须要导入RouteParams
import { RouteParams } from '@angular/router-deprecated'; RouteParams是一个class,ComponentA 初始化时候,
constructor(private routeParams: RouteParams)进行定义, 在constructor或者ngOnInit方法体里,使用 this.routeParams.get('id') 进行参数获取。
import { RouteParams } from '@angular/router-deprecated'; export class ComponentA{ constructor(private routeParams: RouteParams){ console.log("id:", this.routeParams.get('id')) } }
经过Router手动跳转页面:
import { Router } from '@angular/router-deprecated';
class xxx{
constructor(private router:Router){}
go(){
this.router.navigate(['HeroDetail', { id: this.id }]);//参数1路由名称,参数2参数
}
}
事件绑定:
绑定一个事件流,在组件之间通讯。
自定义事件open,在 “组件A” 中定义一个事件 open , 经过 “组件B” 的标签属性绑定 open , 经过 “组件B” 触发
//Component A @component { template: '<b (open)="open($event)"></b>' } class A{
open(){
console.log('done');
}
} //Conponent B import { Component, EventEmitter, Output } from '@angular/core'; class B{ @Output() open= new EventEmitter(); this.open.emit();//emit也能够传参 }
(open)="open($event)",自定义open方法里必需要带上$event,不然不会执行,至于为何以后再研究。
若是是(click) 这种绑定浏览器默认事件,(click)="open()",就能够不用传$event。
小结:
在使用ng2或者说使用ts开发的ng2时,会写入更多的代码用于申明、依赖、定义类型等,好比import,@Input,@Output,在开发的时候会以为很麻烦,
可是这种严格的规范带来的就是更高的可维护性,好比import虽然可能会写不少,可是后期维护某个组件的时候就能很清楚的知道当前组件使用了哪些模块。
编译的时候angular2遵循严格模式,可以帮助避免一些代码错误和不规范。
这趟 “英雄之旅“ 仅仅是一个开始,见识了angular2核心、经常使用的api、组织结构和代码风格。还有不少内容是须要去专研和理解。
虽然涉及不深,可是已经明显感受到,一些angular1中的不足,在angular2中已经不存在了。