1. 程式人生 > >AngularJS 指令解析(二)

AngularJS 指令解析(二)

AngularJS 指令解析(二)


第一篇我們講過了作用域(scope)這塊內容,現在我們進入正題,講AngularJS的指令。

什麼是指令?

這裡我們引用官方的一句話:
Custom directives to access the DOM: In AngularJS, the only place where an application should access the DOM is within directives. This is important because artifacts that access the DOM are hard to test. If you need to access the DOM directly you should write a custom directive for this. The directives guide explains how to do this.

翻譯過來的,總結起來的意思就是應用程式能訪問DOM的唯一通道就是指令。這就是這句話的意思,後面幾句話是解釋,就是說一方面這個東西難測試,另外你想這麼做的話還可以自己寫指令去直接訪問DOM。

在我看來,AngularJS的指令相當於小型的元件,一方面你可以在指令裡面直接操作DOM,另一方面指令模版可以使得程式碼控制的邏輯層面上可以結構分明,降低scope控制上的耦合度。比如一個簡單的伸縮隱藏控制,一般會放到一個介面的作用域裡面去統一控制,但是如果後續有其他同樣的表單也有這樣的處理,那就得每個模組各自寫一套了,控制上也不保證能保持一致。相比之下,我們可以將這樣類似的行為放到一個元件裡面,由元件去自發的控制這個伸縮隱藏,反而可以避免很多不必要的事情。

指令屬性

restrict

這個屬性定義的是指令的使用方法,分別有4種,預設是EA

  • E 指定指令作為元素使用
  • A 指定指令作為屬性使用
  • C 指定指令作為類名使用
  • M 指定指令作為註釋使用

個人推薦的寫法是,指令用A或者C,元件用E,這樣區分起來會很清楚。
而指令用A還是用C取決於指令自身的使用範圍,比如有的指令只是控制一些顯示隱藏什麼的,那A綽綽有餘了,如果還有額外的全域性樣式控制,那還是C靠譜些,這樣程式碼還工整些。

scope

這個屬性定義的是指令的作用範圍,分別有3種,預設是false

  • false 與父作用域共用一個作用域
  • true 繼承父作用域,建立一個子作用域
  • {} 獨立作用域,與父作用域無關聯

個人的選擇依據在於有木有複雜的表單互動控制,若有,則選擇false可以減少一些互動上的問題,反之選true或者是獨立作用域則是需要額外考量的,元件上則獨立作用域會好一點,而子作用域的設立可以通過scope通訊解決一些比較小的通訊問題,同時也能保證作用域在一定程度上的獨立性。

而獨立作用域下有3種方式的通訊

  • @ 屬性偵測
  • & 事件繼承
  • = 雙向繫結(除了ngModel之外)

一般是雙向繫結要好一些,特殊表單可以用雙向繫結,但是資料輸入這塊還是需要transclue的支援,而且直接跟父作用域互動會更好。

template or templateUrl

這個屬性很簡單明瞭,一個是指令模版字串形式,另一個是指令模版地址形式

replace

這個屬性表明要不要做替換插入,false是作為子元素插入,反之是作為替換插入

transclue

這個可以類比vue的slot,內聯插入標籤內部的模版到ng-tranclude指令的標籤內

controller

這個屬性表明指令控制器可以建立scope,scope在link函式裡面是共享的,作為link函式的第一引數,這裡可以寫一些需要繫結的事件,或者是資料處理

這個屬性表示指令編譯完成之後連結到DOM上的一些回撥操作,pre表示連結之前,post表示連結之後,引數(作用域,模版元素,屬性列表,ngModel控制器)

  • pre-link
  • post-link

這裡可以做一些資料監控上的處理,比如屬性監聽,而且對DOM操作比較多的事件可以放到這裡去做而不是在controller裡面

compile

這個屬性指的是自定義的編譯方式,還有一個是引數繫結上的處理,比較危險,一般不建議操作的,引數(模版元素,屬性列表)