jQuery 1.4 小閱兵
14 |
為了歡度jQuery四歲生日(jQuery由John Resig 於 2006/01/14 在 BarCamp NYC 首次發表[註]),jQuery開發團隊在2010/01/14釋出了jQuery 1.4版。
簡單整理一下我所理解的1.4改版重點:
- 大量重構常用的函數,降低程式複雜度(主要是減少內部函數彼此呼叫的次數),達到改善效能的目標。
- *.css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .before(), .after(), .replaceWith(), .wrap(), .wrapInner(), .offset(), .addClass(), .removeClass(), .toggleClass() 可傳入函數,由函數的傳回值當作參數值。(傳入函數當成參數的做法,有個術語叫Function Settter)
- *.css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .offset(), .addClass(), .removeClass(), .toggleClass() 在Function Setter時,該函數的第二個參數即原值。這點很方便,例如,如果要在所有的<a>顯示文字的後方加上"[L]"字串,過去會寫成:
$("a”).each(function(i) { var $a = $(this); $a.html($a.html() + "[L]"); });
現在可以結合2, 3點的新功能,寫成:
$("a”).html(function(i, html) { return html + “[L]”; });
變簡單很多吧! - $.ajax在傳送陣列參數時,預設會改用ary[]=elem1&ary[]=elem2的Query String表示法(過去會轉成ary=elem1&ary=elem2),這多半跟PHP、Ruby on Rails搭配使用。 如果想要保留原做法
,需另外設定jQuery.ajaxSettings.traditional = true;
。 - *$.ajax可不指定dataType,由Response的ContentType決定: applcation/json時自動調為"json",text/javascript或application/x=javascript時變成”script”,text/xml時視為"xml”。
- $.ajax設定ifModified:true時,支援ETag檢查決定是否使用Cache的內容。
- *JSON解析原本都是用eval,從1.4起會在Browser有支援的情況下使用內建的JSON Parser(如: IE8, FF3.1, Chrome, Safari),比eval來得安全也更有效率。
- .serialize支援HTML5的欄位元素,例如: datetime, range。
- *$.ajax多了context參數,在Callback函數中可以透過this直接存取context所傳入的元素物件,不必再用Closure,簡單很多! 例如:
$.ajax({
url: “gettime.aspx”,
context: $(“#spnNowTime”),
success: function(s) { context.html(s); }
}); - $.get, $.post, $getJSON, $.getScript 的success Callback多了第三個傳入參數--XHR。以前若想存取XHR,就必須放棄$.get等簡易寫法,回頭改用$.ajax。
- 送出AJAX Request時不管有無資料內容,一律傳送Content-Type Header,以符合某些應用場合的要求。
- 可以指定JSONP的callback函數名稱了! 也就是在邊做邊學jQuery第14集中提到的jsonp1238089172708,現在可透過jsonpCallback參數自訂。
- $.ajax用onreadystatechange取代setTimeout輪詢,改善效能 。
- .text()支援CDATA
- *很酷的新HTML元素建構寫法:
jQuery("<div/>", {
id: "foo",
css: {
height: "50px",
width: "50px",
color: "blue",
backgroundColor: "#ccc"
},
click: function() {
$(this).css("backgroundColor", "red");
}
}).appendTo("body"); - *.eq(-N), .get(-N)可以取"倒數第N個",.first(), .last()可以取第一個跟最後一個。
- 過去jQuery()會傳回document的jQuery物件,1.4版起則改為傳回空的jQuery集合,以便動態加入元素。jQuery().ready()在1.4仍維持jQuery(document).ready()的效果,但建議不要再用了。
- jQuery(“tagName”)改用getElementByTagName,速度大幅改善;$("<div>”), $(“<div />”), $(“<div></div>”)均改用document.createElement,$(“<div></div>”)效能己改善。
- .css()加快兩倍、.addClass(), removeClass(), .hasClass()加快三倍。
- .toggleClass()支援一次切換多個class,例如: toggleClass("class1 class2")。
- *.data(myCacheObject)可以用傳入的物件置換掉整個Cache物件,而.data()可以取回整個Cache物件。
- .data()使用的Cache物件改成有用到才建立,以改善效能。
- 呈現動畫時,可針對不同屬性設定不同的Easing效果。[參考: 天才少年James Padolsey的Demo]
- jQuery.proxy()可以為現有函數產生一個分身,並指定該分身的Scope(簡單來就是強制指定this)。這有什麼用呢? 常見的案例是在事件函數中,要用另一個元素當作this。例如:
var f = function() { alert(this.id); };
$("#A,#B").click(jQuery.proxy(f, $("#A")[0]));
在A,B上掛了同一個click事件,但透過jQuery.proxy指定Scope為A,則B的click事件裡,this也會指向A。 - .bind()時可傳入物件{ click: function() { … }, keydown: function() { … } },一次指定多個事件。
- *克服了change(), submit()在IE裡跟其他瀏覽器部分行為有差異的問題。
- *新事件focusin, focusout。類似focus及blur,但是支援Bubble Up。應用範例,<p>中包了<input>,當<input>取得焦點時,<p>的focusin事件也會被觸發。
- *除了ready, focus(可用focusin取代), blur(可用focusout取代),所有的事件都可以.live()了,萬歲!!! 另外,live的對象也可以指定Context了。(這應該可以克服上回在滲透式live管不到Iframe document的問題)
- .ready()會使用setTimeout持續檢查document.body是否存在,原則上只用來解決Safari瀏覽器的少數問題案例。
- 非IE瀏覽器不再做unload事件的Memory Leak檢查以加快速度。
- .append(), .prepend(), .before(), .after()變快約一倍,.html()變快三倍,.remove(), .empty()變快4倍。
- 新方法: .detach(),將元素自DOM移除,但保留事件函數,多半用在暫時移除,稍後加回去的情境。
- 新方法: .unwrap(),剝掉外層,留下html()的部分。例如: <div id="X"><span>A</span></div>,$("#X").unwrap() -> <span>A</span>
- 內部函數domManip加入Cache機制,jQuery("<div>"), .after("<div>")會比以前快。
- 沒有加進DOM的物件也可以用.before(), .after(), .replaceWith()。例如: jQuery("<div/>").before("<p>Hello</p>").appendTo("body") 。
- *.clone(true)現在連.data()也一併會複製 。
- .offset()支援設定功能,可用來改變元素位置。(設定時,CSS position會被自動改成relative)
- *queue()不再只侷限在動畫應用上,新增.delay(n)函數,可暫停n ms、.next()可跳到下一個動作、clearQueue()可以清除動作。
- *.index()取得元素在同層元素中的排行,.index(selector)取得元素在同層元素同符合selector的排行。
- .has()。$("div”).has(“a”) 相當於 $("div:has(a)”)
- .nextUntil(), .prevUntil(), parentsUntil(),類似.nextAll(), .prevAll(), .parents(),但會一直向後/前/上蒐集元素,直到符合selector元素為止。
- .add(), .closest()支援傳入第二個參數作為Context 。
- jQuery.isEmptyObject()用來判別是否物件沒有任何屬性 。
- jQuery.isPlainObject()用來判別是否為物件 。
- jQuery.contains(A, B)用來判別元素B是否被包在元素A中 。
- *jQuery.noop(),什麼事都不做的空函數,用在一定要傳入函數作為參數的場合。
- jQuery.unique(),只保留DOM元素陣列中不重複的部分,並依在DOM出現順序排列。
- 其他: jQuery.browser支援Engine導向,例如: jQuery.browser.webkit用來判別所有以WebKit開發的Browser、對Java Applet的支援更好、不再使用arguments.callee(ECMAScript 5要廢掉)、使用Closure Compiler而非YUI Min來壓縮jquery-1.4.min.js 。
【改版後不相容之處】
改用1.4,請注意以下的寫法可能會出問題:
- .add()的結果改成依元素在DOM裡的順序排列
- .clone(true)會一併複製事件跟.data()儲存的資料
- jQuery.data(elem)不再只傳回id字串,而是該元素的.data() Cache物件
- jQuery() != jQuery(document)
- *.val(“…”)作用在<option>或<input type=”checkbox”>時,只認value,不再看text
- *jQuery.browser.version現在傳回Engine版本
- 將會阻擋格式不符規定的JSON表示字串
- *預設會以PHP/Rails的ary[]=elem1&ary[]=elem2方法序列化參數,如想維持ary=elem1&ary=elem2的做法,請設定jQuery.ajaxSettings.traditional = true;
- 內建屬性jQuery.className移除
- jQuery.extend(true, …)將不再適用於非物件及陣列
- *$.ajax未指定dataType,而Response.ContentType == “text/javascript”時,將會自動被當成Script執行,不再當成string處理
- $.ajax的ifModified會一併納入ETags決定是否使用Cache。
好消息是,如果你發現原來的js換了1.4有以上問題,懶得改程式又很想用1.4,只要加掛一個Plug-In就可以解決。
<script src="http://code.jquery.com/jquery.js"></script>
<script src="http://code.jquery.com/jquery.compat-1.3.js"></script>
我只能說,jQuery真是佛心來著呀!!
【註】紅色*是我個人認為值得關注的改變
Comments
# by 路人甲
大大您好 不知您的邊做邊學jquery系列裡的示範是如何達成 就是不用在program model那打程式碼 直接在htm的執行頁面打jquery語法就會直接執行
# by Bonnie
你好: 我這裡遇到一個現象,是使用IE7/8才會發生的,IE6、Firefox 3.5及Chrome 3沒問題。 我在 html 中外部載入一份 a.js,並且於 a.js 中呼叫 $.getScript("b.js"),然後執行 b.js 中的函式。 而這個函式僅簡單 alert("Hello!") 我用IE7/8測試時,「第一次」載入網頁,會跳出「Permission Dynied」的訊息,重新整理後又可以正常顯示「Hello!」 而trace後,發現是卡在 jquery-1.4.js 產生 XMLHTTPRequest 的地方,和1.3.2比對後,發現這版改寫了判斷的方式,我有先咕狗過,這版的寫法看來是比較有彈性也較正確的方式,不過,不知道為何會在IE7/8上出問題。 不知道你是否遇過?該怎麼解呢? 謝謝~
# by Bonnie
你好: 我這裡遇到一個現象,是使用IE7/8才會發生的,IE6、Firefox 3.5及Chrome 3沒問題。 我在 html 中外部載入一份 a.js,並且於 a.js 中呼叫 $.getScript("b.js"),然後執行 b.js 中的函式。 而這個函式僅簡單 alert("Hello!") 我用IE7/8測試時,「第一次」載入網頁,會跳出「Permission Dynied」的訊息,重新整理後又可以正常顯示「Hello!」 而trace後,發現是卡在 jquery-1.4.js 產生 XMLHTTPRequest 的地方,和1.3.2比對後,發現這版改寫了判斷的方式,我有先咕狗過,這版的寫法看來是比較有彈性也較正確的方式,不過,不知道為何會在IE7/8上出問題。 不知道你是否遇過?該怎麼解呢? 謝謝~
# by Bonnie
阿 抱歉 送了兩次 麻煩請直接刪除重複的部份 3Q
# by Ark
a.js中$.getScript("b.js") 是否放在 $(function(){...});內 如果是在ready 就想執行~須注意
# by Jeffrey
to 路人甲,您指的是Mini jQuery Lab吧? 可以參考介紹: http://blog.darkthread.net/blogs/darkthreadtw/archive/2009/02/11/mini-jquery-lab.aspx。邊做邊學jQuery的程式範例中可以找到它的原始程式碼。
# by Bonnie
to Ark, 確實是放在$(function(){...});內 但我不太了解其中的原理,可否說明一下呢?
# by 路人甲
感謝Jeffrey大大 這東西超方便 不用在一直編譯就可測試打的JavaScript對不對 小弟我也想變JavaScript神手!!!
# by Ark
to Bonnie 我猜測的原因是IE有安全性原則的套用問題 啥信任網站的 第2次成功可能是抓快取的
# by Mesak
各位好,最近在寫 一些 greasemonkey 的程式 檔程式越寫越大之後,發現效能越托越慢 我能想到的有幾個問題 1. 物件 重複呼叫 2. 屬性 存取data 是否會影響效能 3. 事件的綁定 請問 還有沒有方法可以增加 jquery 的效能呢??
# by Jeffrey
to Mesak, 依我的經驗,要調效能要先抓出瓶頸,有時瓶頸改兩行的效果遠勝過依據某些效能原則全面改寫程式(當然,平日寫Code就依循效能原則,絕對是正確的,你可以用"jquery performance tips"關鍵找到不少探討文章)。建議可以善用一些工具(如: IE8 Dev Tools, http://bit.ly/ahyzDL)看看程式慢在哪裡,會比應用一般性原則去改寫程式更能有效改善速度,若GreaseMonkey的程式偵錯或監測不易,可設法拉出成一般js驗證後再搬回去。
# by Mesak
謝謝 Jeffrey 的回答跟資料,請問一下 firefox 有類似的 addons 可以監控函式的呼叫次數等 紀錄可用嗎? 因為我是寫 遊戲的腳本,所以 模擬相同的 環境不太容易,所以還是得用 FIREFOX 測試 除錯....
# by Jeffrey
to Mesak, 可試試FIrebug的Profiler功能。(參考: http://getfirebug.com/logging)
# by Mesak
我開啟主控台,json 會被插入 firebug的資訊.....