前言: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中已經不存在了。