jqLite 是 AngularJS 為了方便進行 DOM 操作而又不希望讓 jQuery 成為 dependency 的解決方案,官方文件如是說:
jqLite is a tiny, API-compatible subset of jQuery that allows Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality within a very small footprint, so only a subset of the jQuery API - methods, arguments and invocation styles - are supported.
並且在文件下方給了一串相關 API 文件的連結,連到 jQuery API Documentation 去。
嗯?連到 jQuery API Documentaion 有什麼不對嗎?
前言
爬一爬 jqLite 的 source code 就可以知道,其實它是嘗試照著 jQuery 的部分 API 做 subset-implementation,結果就是雖然它給了 jQuery API Documentation 的連結,它部分 API 的部分功能是與 jQuery 不同的。如果你還是照著使用 jQuery 的用法來使用 jqLite 而沒有做好爬 jqLite source code 的心理準備,應該會有點 happy …
本文整理了 v1.1.5 幾個比較常碰到的地雷,與各位共勉之。
環境設定
- 不載入 jQuery
- 由於 AngularJS v1.2.0 於本文撰寫時尚在 RC2,並且我自己主 project 在使用的版本為 v1.1.5,因此本文針對的版本為 v1.1.5。
.css() as setter 不會自動加上 px 單位
jQuery 除了部分的 css style,其餘 style 在沒有帶入單位的時候,預設都會加上 px 做為單位,而 jqLite 不會幫你加。
// works
iElm.css('font-size', '18px');
// won't work
iElm.css('font-size', 18);Demo
與下一段 getter 一併 Demo。
.css() as getter 不會取 computed style
有些 style 是具有繼承性質的(e.g. font-size, color, etc…),而 jqLite 的 .css() 不像 jQuery 會想辦法取得瀏覽器計算後的結果,它只能夠取得該 DOM element 上已設定的 style 內容。
console.log( iElm.css('font-size') );
// output: ""
// jQuery 的取法
iElm[0].ownerDocument.defaultView.getComputedStyle(iElm[0]).fontSize;Demo
- 利用
<input type=”text”>來修改期望的font-size - 用上一段所說的方法實做了兩種
setter的 directivefont-size-success及font-size-error - 更新
font-size的同時,另一個 directiveget-font-size會嘗試從沒有被直接設定 style 的<span>上取得 jqLite 直接拿的font-size以及計算的font-size
.bind() 與 .unbind() 對 eventType 參數的理解不同
此問題於 v1.2.0rc1 後已修正。
何謂理解不同呢?在 eventType 代入 "play ended pause" 的時候:
.bind()會視為play,ended,pause三個分別處理.unbind()沒有把它們切開,於是根本就會找不到這個 event 來 unbind
// 一次綁三個: play, ended, pause
iElm.bind('play ended pause', playbackHandler);
// 這邊這樣無法 unbind 且不會跳錯誤
iElm.unbind('play ended pause', playbackHandler);
// 一樣無法 unbind
iElm.unbind('play ended pause');
// 成功 unbind,不過基本上把事件都清光了
iElm.unbind();
// 一個一個來會成功
angular.forEach(['play', 'ended', 'pause'], function (evtName) {
iElm.unbind(evtName, playbackHandler);
});
// 對,就是一個一個來
iElm.unbind('play', playbackHandler);
iElm.unbind('ended', playbackHandler);
iElm.unbind('pause', playbackHandler);Demo
bind-unbinddirective 試著將給定的事件.bind()至按鈕上並立刻.unbind()- 實作
.unbind()的方法是上述不會成功的做法,因此嘗試去按鈕上觸發事件還是可以成功執行bind-unbind-trigger的內容 - 歡迎使用
Edit功能將 directive 裡面的.unbind()替換成會成功的做法看看結果
TL;DR
把 jQuery 擺在 AngularJS 前載入,一勞永逸。
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="http://code.angularjs.org/1.1.5/angular.min.js"></script>