指令,是AngularJS
最經常使用的功能,讓咱們很容易在前臺實現代碼複用。而指令最精髓的地方,就在於指令內外域scope
的交互方式。javascript
本文屬於一篇對文檔的翻譯加上一些本身對此的理解,因水平有限,可能某些地方翻譯的不通順,或者翻譯的錯了,歡迎你們批評指正。本文對scope
的用法以及描述均翻譯自AngularJS
英文文檔,文檔地址:AngularJS 官方文檔java
scope
屬性的值能夠是false
,能夠是true
,也能夠是對象。angularjs
false
:這是指令scope
的默認屬性,不會爲指令建立一個scope
,這個指令會使用他的父scope
。api
true
:爲指令建立一個從父scope
原型繼承的子scope
。數組
{key: value}
:爲指令建立一個新的隔離scope
,隔離scope
和一般的scope
的區別在於:隔離scope
不從父scope
作原型繼承。app
不從父scope
作原型繼承,這對於建立可重用的組件很是有用,可重用組件不該該從父scope
讀取或修改屬性。this
注意:一個有隔離scope
可是沒有template
或templateUrl
的指令不會將隔離scope
應用到它的子元素。這是文檔上寫的,目前尚未理解到到底是什麼意思。google
也多是我翻譯的不對,如下是原文:翻譯
Note that an isolate scope directive without a template or templateUrl will not apply the isolate scope to its children elements.
隔離對象定義了源於指令元素的屬性的本地scope
屬性集合。雙向綁定
如下幾種綁定都是能夠加參數的。
例:
scope: { name: '=nameAttr' }
綁定的就是:<test name-attr="'hello'"></test>
。
scope: { name: '=' }
綁定的就是:<test name="'hello'"></test>
。
@
/@attr
:綁定本地scope
的屬性到DOM
屬性的值,這個結果老是一個字符串,由於DOM
屬性就是字符串。隨着DOM
屬性值的改變,指令scope
上的屬性也會改變,由於這個屬性是在它的父scope
上讀取的。
=
/=attr
:本地scope
的屬性和傳遞到屬性上的表達式創建雙向綁定,該表達式是在父scope
的範圍內計算的。若是綁定的表達式不是可賦值的,或者它不是可選的可是指令中沒有傳,$compile:noassign
異常就會被拋出,由於它沒法和父scope
同步。
默認地,$watch
方法一般用來監聽改變,而且根據對象的地址來進行相等判斷。然而,若是一個對象地址或數組地址被傳遞到綁定的表達式中,比較的方法就是經過判斷值是否相等。也可使用=*
/=*attr
和$watchCollection
進行淺監聽。
這段話還不是很理解,在StackOverflow
找到了一個靠譜的回答,但還不是很明白。AngularJS =* 問題
<
/<attr
:在本地scope
和傳遞到DOM
屬性上的表達式之間創建單向綁定,全部在DOM
屬性上表達式的改變會反映到scope
的屬性上,可是scope
屬性上的改變不會反映到DOM
屬性的表達式上。
可是這有兩個警告:
1.單向綁定不是將父scope
的值拷貝到隔離scope
上,而是簡單的設置相同的值。若是你傳的是一個對象,那在隔離scope
上對該對象的改變會反映到父scope
上,由於二者引用同一個對象。
2.單向綁定監視的是父值地址的改變。這意味着在父值上的$watch
僅僅在引用的地址發生改變時纔會生效。大多數狀況下,這是不須要關心的。可是必需要知道若是你單向綁定了一個對象,而後會改變隔離scope
上的對象,若是改變了父scope
上的該對象的一個屬性,這個改變是不會傳遞到隔離scope
上的,由於這個對象的地址沒有改變,除非你賦值一個新的對象。
若是不打算將隔離scope
的改變傳播會父節點,單向綁定是頗有用的。
&
/&attr
:在父scope
提供一個可執行的表達式,就是傳一個方法。
全部的綁定(@, =, <, &
)都能經過在表達式上添加?
設置爲可選的,這個標誌必須在綁定模式以後,屬性名稱以前。
可選和不可選的區別在於:
如下是AngularJS
文檔中對可選指令的示例代碼。
app.directive('testDir', function() { return { scope: { notoptional: '=', optional: '=?', }, bindToController: true, controller: function() { this.$onInit = function() { console.log(this.hasOwnProperty('notoptional')); // true console.log(this.hasOwnProperty('optional')); // false } } }; });