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-unbind
directive 試著將給定的事件.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>