很多Directive會用相同模版對應不同資料產生多個DOM元素,為確保各元素的ViewModel彼此獨立不相互干擾,需要為每筆資料建立一個Isolated Scope。最常見的例子是ng-repeat,例如:

<li ng-repeat="item in collection">
  {{item.prop}}
</li>

當ng-repeat為collection陣列產生成多個<li>,每個<li>都有一個獨立Scope,每個Scope有個item資料物件屬性,對應到collection陣列的每個元素。

像ng-repeat這類常用Directive,其Isolated Scope結構較單純且文件範例完整,並不難掌握,但對於一些複雜的第三方Directive,由於技術文章及相關教學不如官方Directive完整,常會有搞不清楚Isolated Scope有何屬性無從用起的困惑。面對此種困境,除了「Use the source, Luke!」,使用F12開發工具線上偵察也是一種解法。但如何與咻一聲滑進中斷點與Isolated Scope巧遇則是一項考驗,在此分享我常用的偵察技巧。

ui-grid為例: demo

cellTemplate的"{{row.entity.score|number}}"意味每一列資料的Isolated Scope裡有個row屬性,不難猜出row.entity對應的是myData陣列的逐筆元素。但,要如何偵察row元素的完整屬性呢?

方法1:自製debug Filter

我習慣在module裡加入一個中斷點專用Filter,寫法很簡單:

app.filter("debug", function() { return function(value) { debugger; }; });

只要將它串在待偵察物件或屬性後方(例如:{{row|debug}}),一執行到該Filter debugger便會觸發中斷(但留意在Dirty Check機制下,它被呼叫的頻率或許比你想像的高很多),我們就能用F12開發工具仔細調查傳入資料物件的底細。如下圖所示,中斷時在Console面板輸入value可互動檢視row物件的即時資訊。

方法2:angular.element().scope()

debug Filter應用時必須串接在Scope特定屬性之後,Filter接收value參數後只能由該屬性向下層展開,無法一窺Isolated Scope全貌。面對此種需求,我慣用的解法是透過jQuery選取Isolated Scope對應的元素,再以.scope()取得所屬Scope物件。

如以下範例,先設法用選擇器找到65,535所在<div>,scope()可傳回該列對應的Isolated Scope,透過Console檢視內容,我們可以看到$index、$even等ng-repeat也具備的特殊屬性,而有個col會指向該欄對應的欄位設定,至於前面提到的row屬性來自繼承,則藏在__proto__裡,用for (var p in scope)技巧列出scope所有繼承及自身屬性,我們也能把它挖出來。

利用上述兩則小技巧,下回再遇到難以捉摸的Isolated Scope也不用煩惱囉~

 

[NG系列]

http://www.darkthread.net/kolab/labs/default.aspx?m=post&t=angularjs

Comments

Be the first to post a comment

Post a comment