Angular 2 系列: 组件

Angular 2 Series: Components

By Max on April 13, 2015

歡迎來到我們 Angular 2 的第二章。如果你沒看過第一章,點這(介紹Angular2)看看

在這章中,我們將介紹一下組件,這玩意優雅的取代掉了 Angular 1 中的 controller, scope, 和 directive。

scope 死了

也許你沒看過 Igor 和 Tobias 十月份的時候在 ngEurope 上做的精彩演說,但是我當時在場,他們繪聲繪色的宣佈了 Angular 1 的各種概念死亡,包括了 controller 和 scope,當一排讓人不悅的墓碑 duang~ 到大屏幕上的時候,現場人羣裏面緊張的呼吸和莫名的笑聲讓我記憶猶新。

http://blog.ionic.io/wp-content/uploads/2015/04/Screenshot-2015-04-02-16.51.16-274x300.png

之後在社區引起了軒然大波,有 scathing comments, high-profile departures,也有 overly-dramatic banter 讓人足夠興奮。

雖然譁眾取寵確實能賺點擊率,不過過剩反應確實是沒必要。那我們來看看新的 Angular 2 是怎樣用它的組件模型,以更簡單的方式來實現 v1 中的一些功能。

組件

Angular 1 並不是圍繞組件這個概念來站開的。所以,我們需要以 controller 模式,把我們的邏輯依附(attach)到頁面的各個地方。Scope 就被帶到各處,添加或者傳遞,根據你是怎樣封裝你的自定義指令。(isolate scope,有沒有!)。

我真的不是很清楚應該怎麼描述 v1 的模型,不過它真的和我用過的其他系統不一樣。我只能說"依附"各種行為到頁面的各個部分,然後再必須處理這些複雜的我們通過 directive , controller 和 scope 創建的指令元結構(meta-structure)。

為了把邏輯添加到頁面上,我們就得在創建一個 controller 還是 directive 之間做個取捨。

在版本 2 , Angular 把所有這些東西都幹丟到了一個更干淨,更面向對象的組件模型中。

第一個組件

如果你曾經寫過 Java, C#,或者其他強 OO 類語言,你立刻就會明白什麼是組件了。它就是一個類,代表了屏幕上的一個元素,以及一些影響它外觀和行為的成員數據。

就像在 Java(Swing) 裏面的 JComponent 子類,或者在 Windows Forms 裏面的 Control 子類。

讓我們來看看例子:

<!-- lang: js -->
import {Component, Template} from 'angular2/angular2'

@Component({
  selector: 'my-component'
})
@View({
  inline: "<div>Hello my name is {{name}}</div>"
})
export class MyComponent {
  constructor() {
    this.name = 'Max'
  }
  sayMyName() {
    console.log('My name is', this.name)
  }
}

這就創建了一個叫 MyComponent 的新組件,它會定義一個叫做 <my-component> 的標籤,就像在 v1 裏面的 restrict: 'E'

我們可以用 @View 註解(annotation)來指定組件的模板(註解是 AtScript 和 TypeScript引進的 es6 擴展,不過只有 TypeScript 跟進了) 。

成員數據

讓我們再仔細看看上面的例子,我們沒有看到 $scope。相應的,我們看到了 this.name = 'Max',和一個叫做 sayMyName() 的成員方法(“method”)。如果你熟悉 v1 的 Controller As 標籤的話,那你應該也會覺得 this 很熟悉。

不過,它還是有點不一樣。當我們的組件被 “實例化(instantiated)” 和被頁面渲染的時候,我們拿到組件的一個實例。我們可以修改組件實例中的數據,調用它的方法,甚至把它當參數傳給別的組件。就是對象嘛!

再舉個例子,假設我們有一個 Button 控件。控件有一個 this.title 提供按鈕的文字,有一個點擊事件。原來,我們需要為這個按鈕創建一個新的 directive,或者偷懶一點給它(或它的父層)寫一個 controller。在 Angular 2 組件中,我們有了一個更加自然的把這些概念放到一起的方式:我們的組件有封裝起來的數據實例(非常像 isolate scope),事件句柄(非常像在 scope 裏面的方法),還有模板(非常像 directive)。

我們甚至可以從另外的組件繼承它們,或者通過屬性給附加進來,甚至可以訪問父節點以及兄弟節點(暫且按下不提)。這遠比在 v1 裏面用 require 簡單多了。

ngApp

在上一篇帖子裏,我們簡單提到過引導,這是 Angular 2 應用自我啟動的地方。在 v1,我們必須 ng-app 一下或者人工啟動。而 v2,這裏就沒有 ng-app 了。取而代之,我們需要提供根組件,放在我們希望啟動應用的地方:

<!-- lang: js -->
<app></app>

然後是 v2 的組件:

<!-- lang: js -->
@Component({ selector: 'app' })
@View({
  url: 'main.html',
})
class MyApp {
  constructor() {
    console.log('App Start')
  }
}

bootstrap(MyApp)

這就像我們在 Angular 1 中,經常可以看到的 ng-appng-controller 用在同一個元素上,比如:

<!-- lang: js -->
<body ng-app="myspace" ng-controller="AppCtrl">

然後,在我們的 AppCtrl 會創建根 scope 數據,我們的子 controller 可以訪問,或者擴展它。

在 v2,我們把這些都放到了一個組件。

我真的超喜歡這個改變。你想想你的文檔結構,是不是很像一棵樹。根節點是不是應該和別的節點沒什麽不同,即使在 v1。

隨著組件模式的改變,我們的習慣也需要有些改變。我們如果想要把邏輯放到頁面上,現在不是用 controller 了,我們需要給它創建一個新的組件。如果我們想用既存組件,但是又想要追加不同行為,我們需要擴展它。

Annotations

讓我們再深入一點上面提到的 @Component@View 註解。你要記住,這是一個 ES6 的擴展,被 TypeScript 用到了 Angular 2 裏面,是它的一部分。

基本上,這些註解就是給我們的組件提供附加情報用的。我們可以配置選擇器,讓它查找自己的實例(比如 <my-component>),以及設置模板。

@Component 是核心註解,有一些很重要的參數:

<!-- lang: js -->
@Component({
  selector: 'my-component',
  services: [MyService]
})

selector 參數是用來取代在 v1 裏面 directive 的自動命名系統的,現在被改成需要明確指定了:你必須明確指定這個新的組件作為標記的時候的名稱。工作原理和 querySelector 很像。

services 參數是新的依賴注入系統的一部分,它指定了我們想要把哪些服務注入組件(下一篇詳述)。

@View 配置組件的模板,還有那些我們想要用到的子指令:

<!-- lang: js -->
@View({
  // Url based
  url: 'main.html',

  // Inline based
  inline: `
    <div>
      <button></button>
      <content></content>
    </div>
  `,

  directives: [Button]
})

在這個例子裏面,我們看到 url 參數,可以讓我們指定一個外部模板,而 inline 則可以讓組件支持內置模板。請注意這裏: new backtick Template strings ,ES6 的新玩意,能讓我們很簡單的就完成多行模板!

我們還要引入我們希望在組件裏面用到的子指令,這樣它就可以順利的編譯和實例化了(我希望在之後這裏能做改善,你不需要明確的指定引入了哪些子指令)。

最後,我們再看看在我們模板中的 <content></content> 標記。這是新的 ngTransclude ,指定了子視圖會被放到哪裡。你可以有多個子視圖,然後指定多個不同的地方來放它們(之後再說)。

結論

Angular 2 確實發生了許多變化,很戲劇性的我們需要在頁面上創建和指定組件。

雖然從我們喜歡的 scope,controller 和 directive(那些我們超用心去學習和深深愛上的概念)中遷移過來是很痛苦的,但是它真的很值得。由於新的組件模型, Angular 已經變成了我們熟悉的 OO ,並且讓它和之後的 web 標準很接近了,比如說 Web 組件和虛擬 DOM。

一旦你習慣了新的模型,就很難再回去了。我想社區一定會去學會擁抱改變,並很樂於看到它們讓 Angular 2 變得更好。

在下一篇帖子裏,我們將聊一下數據綁定“新方式”:英年早逝的雙向數據綁定!

敬請期待。

你可能感兴趣的:(ionic,angular2)