[料理佳餚] 從 ng-iScroller 來探究 Directive 這個 AngularJS 接地氣的神器

過去我們收集了很多 JavaScript 或是 jQuery 很好用的第三方元件,而用了 AngularJS 之後,這些第三方元件就廢掉了? - 非也。

AngularJS 是用 JavaScript 寫成的框架,並沒有限制與其他用 JavaScript 預先寫好的程式碼做結合,只是我們必須要 follow AngularJS 框架本身的 rule 而已。

我們可以將這些很好用的第三方元件做成 Directive 繼續延用,我就以一個別人寫好的 iScroll Directive 來做為範例,說明一下怎樣把第三方元件做成 Directive。

如果不曉得 iScroll 是做什麼的朋友可以稍微看一下它的官網;別人做的 Directive - ng-iScroller,它的原始碼則在這裡

ngIscroll Directive

我們先看到 ngIscroll Directive 將 Directive 宣告在 ng-iscroll 這個 module 裡面,所以要使用的時候必須 inject ng-iscroll 這個 module,再來就是它只使用了三個屬性,分別是 replacerestrictlink

replace 設定成 false,表示不會取代掉原本的 HTML 元素。

restrict 指定為 A,表示 Directive 只能以 HTML attribute 的樣子被使用。

最後就是 link 函式,在[食譜好菜] AngularJS 基本術語及生命週期裡面有提到,link 函式會在 view 被渲染之前與 scope 組合,這時候 link 函式就會被執行,因此 iScroll 元件的事件及行為都會被建立在這裡,我們一一來看 ngIscroll 在 link 函式內做了什麼事情。

Line 29 ~ 47

首先在這個程式碼區段,它宣告了三個變數:ngiScroll_timeout 值是 5、ngiScroll_opts 是要給 iScroll 用的預設的設定屬性、scroll_key 從 ng-iscroll 或 id 這兩個 HTML attribute 取得被賦予的值。

Line 49 ~ 59

接著在這個程式碼區段,它檢查在父 scope 內是否有被定義 myScrollOptions 這個 object,然後從 myScrollOptions 中將屬性值一一取出,用來覆寫原先預設要指定給 iScroll 用的屬性值。

ngIscroll 用了一個技巧,它利用 scope.$parent 來與其他 scope 做資料交換。

Line 61 ~ 78

這個程式碼區段有三個小段:

  1. setScroll() 看著註解應該也知道,這邊就是建立 IScroll 實例的地方。
  2. 檢查從 ng-iscroll-delay 這個 HTML attribute 是否能取得到值?並且覆寫掉 ngiScroll_timeout 這個變數。
  3. 將從 ng-iscroll HTML attribute 取回的字串值當成要監聽的 watchExpression,當資料異動事件被 trigger 的時候執行 setScroll()。
ngIscroll 用了一個技巧,它利用 $watch 在初始化時至少會執行一次的特性,來建立 iScroll 的實例,不過這種手法有個小缺點,它會讓 AngularJS 浪費一個 watcher 用來監聽不會改變的值。

Line 80 ~ 93

當資料更新的時候,要維持 iScroll 的效果必須要呼叫 refresh() 來更新 iScroll 實例的屬性,因此 ngIscroll 讀取了一個 ng-iscroll-refresher HTML attribute 的值來當作 watchExpression,當資料異動事件被 trigger 的時候執行 iScroll 實例的 refresh() 方法。

最一個程式碼區段就是當 scope 被解構的時候,iScroll 實例也跟著被解構。

如何使用

我們只要在網頁中,在想要有 iScroll 效果的 HTML 元素中加上 ng-iscroll attribute 就可以了。

 < Source Code >

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學