前文所說,jQuery 1.9是一次"拿掉哪些東西"比"增加哪些東西"來得重要的升級,大刀闊斧地移除及改掉許多不一致或沒效率的API,而革命總免不了要流點血(還記得jQuery 1.6的.attr()/.prop()事變嗎?),雖然大部分的過時(Deprecated)API在過去1.7/1.8版釋出時就已強調過,但許多開發者可能跟我一樣,老師在講也沒在聽,過去怎麼寫就繼續寫下去。終於,1.9正式把這些過時API刪的刪改的改,該是面對現實的時候了! (當然,貼心的jQuery RD仍提供了繼續鴕鳥龜縮的選擇)

也因為1.9變動幅度較大,為減輕大家改版的痛苦,官方特別出了一份jQuery Core 1.9 Upgrade Guide,羅列升級1.9版的注意事項。為了避免升級1.9變成天堂路,這份指南不可不讀,閱讀之餘,順便摘要寫成筆記,備忘兼分享:

  1. 請善用jQuery Migrate外掛,可以暫時避開程式壞光光的困境(但這樣子搞,換到1.9的意義不大),並能自動列出程式不相容的地方。(記得要使用未壓縮的開發版jQuery Migrate才會顯示不相容警告。雖然加掛jQuery Migrate後老程式大部分都可繼續正常運作,建議還是趁早改掉過時API為宜,老話一句: 出來混遲早要還!)
  2. 移除.toggle(fn1, fn2)
    讓toggle()回歸"切換元素顯示與否"的單一用途。[可透過jQuery Migrate還原]
  3. 移除jQuery.browser()
    1.3就已宣告過時,1.9終於拿掉。[可透過jQuery Migrate還原]
    建議改用Modernizr
  4. 移除.live()
    1.7宣告過時,1.9正式移除。建議改用.on()。[可透過jQuery Migrate還原]
  5. 移除.die()
    1.7宣告過時,1.9正式移除。建議改用.off()。[可透過jQuery Migrate還原]
  6. 移除jQuery.sub()
    因為使用頻率低,移出核心程式庫,有需要請加掛jQuery Migrate。
  7. .add()
    1.9版起,加入後節點元素將會依其在DOM的出現順序排列,沒掛入document的元素擺在最後。
  8. 以.addBack()取代.andSelf()
    1.8版建議用.addBack()取代.andSelf()以求正名,另外.addBack()還多支援選擇器參數進行過濾。例如: $("section,aside").children("ul").addBack("aside")會得到section與aside下所有ul外加所有aside元素。.andSelf()在1.9仍可用,但jQuery Migrate會提出警告。
  9. 離線節點的.after(), .before(), .replaceWith()
    1.9版前,若針對未放進DOM的離線節點元素進行.after()、.before()、.replaceWith(),有時會傳回看似相同卻非原集合的結果,1.9已排除此一令人困擾行為。
  10. AJAX全域事件應永遠以document為對象
    過去如有$("#boo").ajaxStart(fn);的寫法,請改為$(document).ajaxStart(fn);
  11. .trigger()事件時的Checkbox/Radio checked狀態
    1.9版之前,當使用.trigger("click")或.click()觸發Checkbox及Radio時,在事件中會看到與實際checked屬性相反的狀態(詳情可參考舊文),1.9終於撥亂反正。
  12. focus事件觸發順序
    理論上,呼叫某個元素.focus()時,應先觸發前一焦點元素的blur事件再觸發新取得焦點元素的focus事件,但1.9版前順序相反,會先觸發新焦點元素focus事件才觸發原焦點元素的blur事件,1.9已修正此問題。
    注意: 直接呼叫DOM元素的.focus(),只有在元素原本未取得焦點且可成功取得焦點時才觸發focus事件;呼叫jQuery的.focus()則無論成功與否都會觸發focus事件。另外,IE6-10 focus事件會以非同步方式執行,讓jQuery.trigger("focus")難以掌握事件執行狀態,會造成focus事件重覆執行,建議改用DOM內建的focus()較單純,例如: $("#boo").get(0).focus()。
  13. jQuery(htmlString)與jQuery(selectorString)
    1.9版以前,jQuery以字串中是否包含HTML標籤來判定傳入的是HTML字串要建立元素? 還是選擇器字串要選取元素? 在某些情境可能將選擇器字串誤判為HTML字串。
    1.9版起改為一定要以"<"開頭才視為HTML字串,遇到無法符合此要求的HTML字串可使用$($.parseHTML(htmlString))克服。 加掛jQuery Migrate後將恢復原本行為。
  14. .data()取得名稱含"."的資料
    從1.9起,.data("abc.def")只會取回名為abc.def的資料,原本還可取得abc的密技已取消。此點就算掛了jQuery Migrate也回不去。
  15. 離線節點(Disconnected Nodes)的順序
    原則上jQuery集合中節點應依照其在DOM出現順序排列。而在1.9版前,若jQuery集合中混雜掛在DOM的節點及未放進DOM的離線節點,則可能出現不可預期的隨機排序。
    1.9起jQuery集合一律改為先依DOM的順序排列節點,最後再加上離線節點。原來的隨機排法太鳥,jQuery Migrate決定無視它,無從恢復。
  16. HTML字串中的Script
    在1.9版以前,$(htmlString)、.append()、.wrap()會執行HTML字串所包含的Script部分並將之移除以免重覆執行,但這違背某些稍後想再執行的情境。1.9版改為仍保留Script但標註為已執行過。
    只是,把JavaScript跟HTML混在一起的現法實在不怎麼入流,這點大家就當成沒看到吧!
  17. .attr()與.prop()
    曾在1.6版造成爭議的.attr()與.prop()分離,1.6.1版屈於現實又改回相容。1.9再次捲土重來,讓.attr()、.prop()明確區隔,減少應用上的混淆。念舊或不想改Code的人,請靠jQuery Migrate繼續當鴕鳥。
  18. 老IE與$("input").attr("type", newType)
    1.9版前為遷就IE6/7/8,不允許透過attr()方式修改<input> type,呼叫時會抛出錯誤;1.9起解禁,開發者可以在IE9+及其他瀏覽器以.attr()改變input type,但如在IE6/7/8(老IE)上出錯後果自負。使用jQuery Migrate後,$("input").attr("type", newType)不會丟出例外,但console會有警告訊息。
  19. hover虛擬事件
    1.9版起,事件名稱"hover"將不再是mouseenter mouseleave的替代縮寫,而是指開發者要自訂hover事件。如需修改可尋找與取代一下就搞定,實在不想改,用jQuery Migrate還原吧!
  20. jQuery物件的.selector屬性
    過去保留.selector是為了.live(),1.9拿掉.live(),.selector也一併移除,掛jQuery Migrate也回不去了。
  21. jQuery.attr()
    1.9版移除了jQuery.attr(elem, name, value, pass)密技,用jQuery Migrate可恢復。
  22. jQuery.ajax取JSON結果時的空字串解析
    1.9版前,$.ajax()取JSON/JSONP結果如遇伺服器傳回空字串時會將結果設為null,仍算JSON解析成功;1.9版起,空字串將被視為無效JSON觸發錯誤,可使用error事件捕捉。
  23. jQuery.proxy()
    1.9版前,$.proxy(null, fn)、$.proxy(undefined, fn)的this會指向window,而$.proxy(false, fn)的this則指向new Boolean(false);1.9起若context傳入null/undefined/false,函數的this會維持原先context,不被改變。
  24. .data("events")
    取回事件資料結構的密技.data("events")取消了! 用jQuery Migrate可恢復之
  25. Event事件移除部分屬性
    Event物件的attrChange、attrName、realtedNote、srcElement屬性自1.7版因無法跨瀏覽器已被宣告過時,1.9版正式移除。如要引用請透過event.orginalEvent存取或安裝jQuery Migrate恢復之。
  26. 其他消失的密技
    jQuery.data()、jQuery.removeData()、jQuery.attr()移除了某些未列在文件的參數呼叫方式。
    另外,文件沒寫的jQuery.deletedIds、jQuery.uuid、jQuery.attrFn、jQuery.clean()、jQuery.event.handle()、jQuery.offset.bodyOffset()也被移掉了,有在偷用的同學摸摸鼻子改程式吧!

【結論】

這次jQuery 1.9版升級加入的新東西不多,但API改變頗大,且某些屬常用寫法(如.live(), .attr(), .prop()),極可能造成現有程式不相容。雖然加掛jQuery Migrate可還原大部分的原有API行為,但如此便失去了1.9版API整頓與效能改善的意義,既然未來要升級更新版本遲早得面對,不妨趁早調整程式,至少新開發的程式就別依賴jQuery Migrate,好好擁抱1.9。


Comments

# by 小黑

黑大太威了

# by Ike

有沒有建議的 .toggle(fn1, fn2) 取代方式呢? 不才的我只有想到用 click 加計數器方式…

# by Jeffrey

to lke, 大家的解法應該都跟你差不多,參考: http://stackoverflow.com/questions/14490957/what-is-alternative-to-use-after-jquery-1-9-removed-togglefunction-function

# by Ike

瞭解了,謝謝~

# by chihwen

.andSelf() 誤植為 .addSelf()

# by Jeffrey

to chihwen, 謝謝指正!

Post a comment