jQuery升級踩坑大全

2021-02-20 全棧開發者中心

 背景

  jQuery想必各個web工程師都再熟悉不過了,不過現如今很多網站還採用了很古老的jQuery版本。其實如果早期版本使用不當,可能會有DOMXSS漏洞,非常建議升級到jQuery 1.9.x或以上版本。前段時間我就主導了這件事情,把公司裡我們組負責的項目jQuery版本從1.4.2升級到了jQuery 1.11.3。jQuery官方也為類似升級工作提供了jQuery Migrate插件。

  言歸正傳。

 坑從何處來

  jQuery 1.11.3是1.x時代的最後一個版本(作者更新:2016年1月8日,jQuery 1.12.0上線,jQuery 1.11.3不再是1.x時代最後一個版本了),由於我的部門項目已經有一定年頭了,當時還是採用的jQuery 1.4.2,這次升級步子邁得算是比較大。早期時候jQuery的很多寫法,在新版本中已經被廢棄,亦或者有些不規範的寫法,當時版本還能支持,但是現在已經不支持。更糟糕的情況是,新版本還支持,但是功能已經和以前不一樣了……這種情況連個錯都不會報,需要深入到代碼邏輯裡面去看。

  jQuery官方推薦了jQuery Migrate 庫來解決jQuery升級問題。不過一直採用這個庫終究不是長久之計,開發中建議使用jQuery Migrate的開發版,可以在瀏覽器控制臺上列印出來不兼容的地方詳細信息。需要注意的是開發中一定要使用jQuery Migrate的開發版,因為壓縮版的是不會在控制臺給出警告的……把jQuery Migrate的庫緊跟在jQuery庫後面引用即可:

<script src="<path>/<to>/jquery-1.11.3.js"></script><script src="<path>/<to>/jquery-migrate-1.2.1.js"></script>

  等升級完畢,確定沒問題了之後,再將jQuery Migrate庫去掉就可以了。根據個人經驗,下面我把坑分成 常見坑,少見坑兩類來論述。

 常見坑  1. 使用了被廢棄的jQuery.fn.live方法

  jQuery Migrate庫對此錯誤也在控制臺有相應的警告:

JQMIGRATE: jQuery.fn.live() is deprecated

  live方法原本的作用是設置事件代理,該方法在jQuery1.7之後就不推薦使用了,取代之的是jQuery.fn.on函數。他們的接口分別是:

$(selector).live('click', function(){/* some code */});$(selector).on('click', [selector,] function(){/* some code */});

  乍一看,中括號裡面的參數可以省略掉,倆函數不是一模一樣麼?於是天真地把函數名live直接替換成on,大部分時候,這麼做好像沒有引起任何異常。但是如果在你調用on函數的時候,前面的$(selector)在當前的網頁上根本不匹配任何元素(該元素可能是後面的代碼才加到DOM裡的),那是不會綁定成功的。事實上,live函數將$(selector)代理到了document元素上,這個元素是肯定存在的,所以不會出現類似情況。正確的替換方法應該是:

$(selector).live('click', function(){/* some code */}); 替換為$(document).on('click', selector, function(){/* some code */});

  2. 使用了被廢棄的jQuery.fn.die方法

  jQuery Migrate對此錯誤的警告是:

JQMIGRATE: jQuery.fn.die() is deprecated

  這個方法和前面的live剛好反過來,取消事件處理函數的綁定。新版本中應該使用off函數代替之,替換方式類似。

  3. 使用了被廢棄的jQuery.fn.toggle函數

  jQuery Migrate對此錯誤的警告是:

JQMIGRATE: jQuery.fn.toggle(handler, handler...) is deprecated

  早期jQuery中名字叫toggle的函數有兩個,一個是用於控制元素的顯示和隱藏,這個用途的函數目前jQuery中依舊存在;另一個就是上面提到的被廢棄的toggle函數,它用於綁定至少兩個函數到同一個元素,點擊該元素的時候兩個函數交替著執行。這兩個同名函數功能相差甚遠,為了不引起誤導,在jQuery 1.8中就不再建議使用了。替換的方式是把兩個函數合併成一個函數的if-else兩個區段,然後自己設置一個boolean變量,控制每次點擊時應該執行哪個區段即可。

  4. 使用了被廢棄的jQuery.browser屬性

  jQuery Migrate對此錯誤的警告是

JQMIGRATE: jQuery.browser is deprecated

  在前端開發中我們經常要根據不同的瀏覽器版本做出不同的處理,jQuery.browser本來是通過瀏覽器的userAgent欄位來提取瀏覽器相關信息的。新版本中已經將其廢棄,而是建議使用特徵檢測的方法去判斷,並且給了一個Modernizr庫作為推薦。不過,改成這個庫可能改動成本有點大,如果你還是想沿用jQuery.browser的思路的話,可以自己去實現一下它。例如,判斷是不是IE瀏覽器,可以用

/msie/.test(navigator.userAgent.toLowerCase());

  即自己手動獲取userAgent欄位,並且做一個正則表達式匹配。其他瀏覽器思路類似,都是對navigator.userAgent做一個正則匹配。

  5. $(html)格式書寫錯誤

  在jQuery Migrate中,出現以下三種警告中的任何一種,都是屬於這個錯誤:

1. JQMIGRATE: $(html) HTML strings must start with '<' character2. JQMIGRATE: $(html) HTML text after last tag is ignored3. JQMIGRATE: HTML string cannot start with a '#' character

  這個錯誤還是蠻值得注意的,因為我們文章開頭所說的jQuery低版本有XSS漏洞,其實就是和這個錯誤有關係。在javascript中我們經常會直接將一段html格式的字符串寫在jQuery引用裡面,比如$('<div></div>')。按照新版本的jQuery要求,這段html格式的字符串必須是以左尖括號(小於號)開頭,其他字符都不可以。以下幾種寫法,都是錯誤的:

1. $(" <div></div>"); //錯誤,字符串最開頭有一個空格,不是以小於號'<'開頭的2. $("<div></div>test"); //不標準,html標籤結束後後面還有多餘的"test",它會被忽略3. $("#<div></div>); //錯誤,以井號開頭並且後面並不是一個css選擇器

  這一點在書寫的時候注意一下就可以了,其實還是很容易避免的。其中第三種錯誤其實就不僅僅是警告了,jQuery會直接拋出一個錯誤,停止javascript代碼的繼續執行。一般情況以井號開頭,例如$("#test"),其實就是一個普通的選擇器,但是上面例子中後面又夾雜著html字符串,這會被jQuery判斷為潛在的XSS攻擊。

  6. jQuery.fn.attr方法的錯誤使用(這是個非常易犯的錯誤!)

  jQuery Migrate中,關於attr方法的警告有以下這些:

1. JQMIGRATE: jQuery.fn.attr('value', val) no longer sets properties2. JQMIGRATE: jQuery.fn.attr('value') no longer gets properties3. JQMIGRATE: jQuery.fn.attr('checked') may use property instead of attribute4. JQMIGRATE: jQuery.fn.attr( props, pass ) is deprecated

  實踐中我發現,早期寫的代碼裡面,獲取一個input輸入表單的值時,是怎麼獲取的呢?$('input').attr('value');又是怎麼設置的呢?$('input').attr('value', 'helloworld')。這在新版本中都是不正確的!正確的做法應該是

$('input').val(); //獲取input表單現在所輸入的值$('input').val('helloworld'); //設置input表單輸入的值

  到底是獲取還是設置,只取決於調用val方法時有沒有帶著參數。

  如果你想手動設置單選框(例如<input type="radio">)被選中,應該怎麼設置呢?老的代碼裡面可能會看到這樣 $('input').attr('checked', true)或者$('input').attr('checked', 'checked')。這些現在也都是不正確的!正確的做法應該是

$('input').prop('checked', true); //把單選框設為選中狀態$('input').prop('checked'); //獲取單選框是不是被選中了,返回true或false

  這是從jQuery 1.6版本開始使用的寫法。如果設置disabled和selected屬性,也是使用prop方法。那到底什麼時候使用attr方法呢?兩者的區別是:prop設置的是某元素固有的屬性,而attr設置的是寫在html標籤上的自定義屬性。舉個例子:

<input type="checkbox" checked="checked" haha="hello" >var v1 = $('input').prop("checked"); //返回true/false,是否被選中,隨狀態改變而改變var v2 = $('input').attr("checked"); //返回"checked",這是你設置在標籤上的,不會變var v3 = $('input').attr("haha"); //返回"hello",自定義屬性var v4 = $('input').prop("haha"); //返回undefined,根本沒有這個固有屬性

  上面提到的第四個錯誤,jQuery.fn.attr(props,pass) is deprecated這個警告在真實項目中從未見到過,看了一下源碼,觸發該警告的jQuery寫法很少見,可忽略。

  7. 向$.parseJSON傳入了非法的參數

  在jQuery Migrate中,該錯誤產生如下警告

JQMIGRATE: jQuery.parseJSON requires a valid JSON string

  jQuery之所以改這個接口,是為了和瀏覽器自帶的JSON.parse接口對齊,從jQuery 1.9開始生效。這個問題常見於AJAX接收服務端返回值的時候。服務端可能返回一個空字符串,這時候調用該接口會產生錯誤。必須向$.parseJSON傳入合法的JSON字符串。修正方法如下:

var v1 = $.parseJSON(str); 替換為var v1 = $.parseJSON( str ? str : "null" );

  8. 使用了被廢棄的'hover'事件字符串

  在jQuery Migrate中該錯誤產生如下警告

JQMIGRATE: 'hover' pseudo-event is deprecated, use 'mouseenter mouseleave'

  在註冊事件處理函數時,'hover'以前可以看作是'mouseenter mouseleave'兩個事件的別稱。目前已經將該別稱去掉了,所以代碼中請用'mouseenter mouseleave'替換之。

  9. jQuery.fn.andSelf已經被替換,不能再使用

  jQuery Migrate中是這樣的警告:

JQMIGRATE: jQuery.fn.andSelf() replaced by jQuery.fn.addBack()

  兩個函數功能是完全一樣的,可以直接替換。

  以上,就是在jQuery升級中常見的問題,當然,本著精益求精的精神,我們還是需要研究一下不常見的問題是什麼樣子的。需要指出的是:下面的問題在我的實際項目中從來沒有碰到過,比較少見,但也無法保證一定不會出現在你的項目中,僅供感興趣的程式設計師們參考吧。

 少見坑  1. jQuery不兼容瀏覽器的怪異模式

  這個錯誤的觸發方式非常簡單,直接把html頁面最頂端的<!DOCTYPE html>標籤刪掉就可以了。瀏覽器怪異模式是為了兼容老古董網頁而設計的,詳情可參考這篇文章:連結。我想現在的WEB程式設計師應該不會傻到不寫DOCTYPE,也很少使用這種模式下的瀏覽器吧。

  jQuery Migrate展示的錯誤警告如下:

  2. AJAX全局事件必須綁定到document節點上

  jQuery Migrate中的警告如下:

JQMIGRATE: AJAX events should be attached to document: ajaxStart

  jQuery中AJAX全局事件包括如下接口ajaxStart, ajaxStop, ajaxSend, ajaxComplete, ajaxError, ajaxSuccess。因為這些事件使用的比較少,所以也歸在少見坑當中。從jQuery 1.9開始,這些事件只能綁定到$(document)上。改正方法如下(摘自jQuery官網):

$("#status").ajaxStart(function(){ $(this).text("Ajax started"); }); 修改為$(document).ajaxStart(function(){ $("#status").text("Ajax started"); });

  3. IE6/7/8瀏覽器不支持修改input表單的type屬性

  在jQuery Migrate中是這樣的警告:

JQMIGRATE: Can't change the 'type' of an input or button in IE 6/7/8

  改變input的表單的type屬性,你可以直接把文本框改成單選框,改成多選框等等。雖然我感覺這是一種並不算優雅的行為,但是很多瀏覽器都是支持這麼做的,除了IE6/7/8。建議在實際中也是少用這個功能為好。

  4. 使用了被移除的$.clean, $.event.handle, $.attrFn, $.fn.data('events'), jQuery.event.trigger屬性與方法

  在jQuery Migrate中是這樣的警告:

1. JQMIGRATE: jQuery.clean() is deprecated2. JQMIGRATE: jQuery.event.handle is undocumented and deprecated3. JQMIGRATE: jQuery.attrFn is deprecated4. JQMIGRATE: Use of jQuery.fn.data('events') is deprecated5. JQMIGRATE: Global events are undocumented and deprecated

  如果你在自己的代碼中使用過這五個接口,那確實是仔細研究過jQuery原始碼的高人啊。因為這五個接口從來沒有出現在jQuery的官方文檔中,並且有些在後續版本中已經刪除,可謂來無影去無蹤。看原始碼的話在早期版本有機會找到他們的存在,但是並不建議使用。建議採用其他方法實現相應的功能。什麼?你不知道這五個函數是什麼功能?那最好了,你現在也不需要知道了……

  5. 使用了過時的$.sub()方法

  jQuery Migrate中對本問題的警告如下:

JQMIGRATE: jQuery.sub() is deprecated

  這個接口非常簡單,不接受任何參數。它用來創建一個jQuery的副本。該方法在jQuery 1.7版本開始就已經不再使用。

  6. 使用了過時的jQuery.fn.error方法

  jQuery Migrate中對本問題的警告如下:

JQMIGRATE: jQuery.fn.error() is deprecated

  在jQuery中,error也是和click一樣的事件。註冊該事件的處理函數,以前是$(selector).error(function(){}),現在已經被廢棄,可以使用$(selector).on('error', function(){})來替代。

 示例代碼

  本文既然自稱為「XX大全」,那就應該儘量的全面一些。為了搞明白這些坑是怎麼踩進去的,我們最後來寫一段js代碼,要求是用最少的代碼,把jQuery Migration庫中所有的坑都踩一遍……也就是讓jQuery Migration庫列印出來它能列印的所有警告。最終的代碼如下所示(博客園竟然沒有辦法上傳附件,只能貼代碼了),非常簡單易懂。打開index.html文件,然後再按F12鍵打開控制臺,你就可以看到壯觀宏偉的控制臺警告了^_^

<!-- filename : index.html --><!--<!DOCTYPE html>--> //keng0 怪異模式<html> <head> <meta charset="utf-8" /> <title>jQuery升級踩坑大全</title> <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.4.min.js" ></script> <script type="text/javascript" src="http://code.jquery.com/jquery-migrate-1.2.1.js" ></script> </head> <body> <div id="a">a</div> <input type="radio" id="b" value="b" /> <input type="radio" id="c" value="c" /> <div id="d" value="d">test</div> <script type="text/javascript"> //開始踩坑 //使用被廢棄分$.attrFn方法 var keng1 = $.attrFn || {}; //該函數在jQuery內部調用,真實項目中從未見過,可忽略,這裡只是為了觸發一下錯誤警告 var keng2 = $.attr($("#a"), "class", "xxx", true); //IE6、7、8中不支持改變輸入框的類型 var keng3 = $("input#b").attr("type", "text"); //在該使用prop的地方使用了attr var keng4 = $("input#c").attr("checked", true); //使用attr獲取property的值,正確的是應該使用 .val() var keng5 = $("div#d").attr("value"); //使用attr設置property的值,正確的是應該使用 .val('somevalue') var keng6 = $("div#d").attr("value", "abcd"); //html字符串必須以'<'開頭(下面這個是以空格開頭) var keng7 = $(" <div></div>"); //最後一個tag後面還有多餘字符串 var keng8 = $("<div></div>abc"); //html字符串不可以以井號『#』開頭 try{ var keng9 = $("#<div></div>"); }catch(e){ console.error(e); } //$.parseJSON的參數必須是合法的JSON字符串 var keng10 = $.parseJSON(undefined); //使用被廢棄的$.browser var keng11 = $.browser; //使用被廢棄的$.sub var keng12 = $.sub(); $("#c").on("click", function(){}); var keng13 = $("#c").data("events"); //調用了已經不再使用的函數andSelf,該函數已經被addBack替代 var keng14 = $("#c").nextAll().andSelf(); //使用被廢棄的$.clean方法 try{ var keng15 = $.clean(); }catch(e){ console.error(e); } //"hover"字符串註冊事件已經被拆成"mouseenter"和"mouseleave"兩個 var keng16 = $("#d").on("hover", function(){/*some code*/}); //jQuery.event.handle並沒有收錄到官方的API中,新版本已經被移除 var keng17 = function(){ $.event.handle.apply(this, arguments); }; //全局AJAX事件處理必須綁定到document對象上 var keng18 = $("#c").ajaxStart(function(){}); //使用了被廢棄的error方法 var keng19 = $("#c").error(function(){}); //使用了被廢棄的toggle方法 var keng20 = $("#d").toggle(function(){/*some code*/}, function(){/*some code*/}); //使用了被廢棄的live方法,應該使用on方法替代之 var keng21 = $("#a").live("click", function(){/*some code*/}); //使用了被廢棄的die方法,應該使用off方法替代之 var keng22 = $("#a").die("click"); //使用了全局事件函數,目前全局事件只支持AJAX那幾個,其他全局事件都不支持 var keng23 = $.event.trigger("click"); </script> </body></html>

  via:http://www.cnblogs.com/xuning/p/5123617.html


相關焦點

  • jquery中淡入淡出切換效果函數使用方法?
    jquery是javascript很常用和熱門的一個類庫,前端開發人員必須學習的一個js類庫,接下來來看看怎麼使用jquery中的怎麼切換使用淡入淡出方法。jquery最大的特點就是極大地簡化了 JavaScript 編程。而且使用起來也是很簡單的,比javascript更方便簡單。
  • jquery技巧之讓任何組件都支持類似DOM的事件管理
    發布-訂閱模式很多博客包括書本上都說javascript要實現組件的自定義事件的話,可以採用發布-訂閱模式,起初我也是堅定不移地這麼認為的,於是用jquery的$.Callbacks寫了一個:define(function(require, exports, module) {     var $ = require('jquery
  • 申請百家號屢次踩坑,直至這個百度帳號無法再申請了
    【摘要】為避免其他新手註冊百家號時重蹈覆轍,介紹介紹我申請百家號時是如何屢次踩坑的,並提醒新手申請註冊百家號時幾個重要的注意事項。
  • 原神新人必須避開的4個坑!都知道是坑,很多老玩家卻依舊在踩
    如果說當前什麼遊戲最火,那一定是《原神》,但如果說當前什麼遊戲裡坑最多,那還是《原神》!很多新玩家入坑,都會碰到這樣或那樣的坑,剛入坑的時候不明所以,踩坑也是情理之中,但很多玩家玩到45級、50級依舊在踩這些坑,就很神奇了,就比如說下面這幾種情況。
  • 每個程式設計師都會的 35 個 jQuery 小技巧
    驗證元素是否存在於jquery對象集合中$(document).ready(function() {    if ($('#id').length) {      } }); 26.引用Google主機上的Jquery類庫 <SCRIPT src="http://www.google.com/jsapi"></SCRIPT> <SCRIPT type=text/javascript> google.load("jquery", "1.2.6"); google.setOnLoadCallback(function
  • jQuery的fadeIn()、fadeOut()和fadeTo()設置元素的淡入淡出效果
    ><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title></title><script src="jquery
  • 使用jQuery的animate()+CSS樣式實現動畫效果及stop()停止動畫
    DOCTYPE html><html><head><title></title><script src="jquery-3.3.1.js"></script><script type="text/javascript">function f1() {$("#div1").animate({ left: '100px
  • jQuery使用hide()和show()隱藏顯示元素,toggle()顯示和隱藏切換
    DOCTYPE html><html><head><title></title><script src="jquery-3.3.1.js"></script><script type="text
  • jQuery的$.get()、$.post()和$.ajax()以GET/POST方式請求數據
    </title><script src="jquery-3.3.1.js"></script><script type="text/javascript">function getNETData() {var d = $.get("Handler1.
  • 我也是大俠武功升級攻略大全 武功升級技巧詳解
    我也是大俠中武功升級是非常重要的,那麼到底要怎麼升級效果最好呢?希望下面這篇我也是大俠武功升級攻略大全能幫到大家。
  • 三國志戰略版攻略S4賽季平民玩家開荒這4個坑不要踩
    大家好我是零氪玩家-花席,上一篇講了平民如何用36-48小時開荒7本後,有的小夥伴成功7本了,有的踩到坑裡面失敗了。花席從5.10日開荒到5.14日早上開了6級野地,S4賽季的開荒終於結束了。這篇文章介紹一下S4開荒有哪些坑,大家看了就能夠避免踩坑。
  • 盤點那些年踩過的母嬰用品的坑!踩坑率高達80%,寶媽含淚分享!
    功課做了無數,坑也踩了無數...說得就是我吧!!!今天決定說說我那些年翻車的母嬰用品,姐妹們記得避雷!別再步我的後塵了!真要說完那真是三天三夜講不完了,但其實雖然踩坑無數,但我買到的好東西也不少呢!(畢竟踩雷也得講究個概率...)1.德國嫩芙葉酸孕紋霜生娃擱置2天,產後趕緊又塗了起來。
  • 筆記本電腦選購要注意套路,這些坑小白最好別踩,謹慎總比被坑好
    每當聊天起電腦話題時,有不少人都會說,選購硬體組裝電腦,由於對電腦硬體的不熟悉,很容易被商家套路設坑讓人踩,倒不如直接買筆記本電腦,可能來得更簡單一些。筆記本電腦實際上,就是算是選購筆記本電腦,如果經驗不足或粗心大意也有會被坑的可能。所以小白們在選購筆記本電腦時,這些坑最好別踩,小心謹慎一點總比被別人坑的好。
  • 《明日方舟》卡達怎麼樣 技能升級材料大全
    導 讀 明日方舟卡達是新推出的4星術師幹員,那麼卡達技能升級需要什麼材料呢?
  • 裝修不踩坑,廚房裝修這5大坑你踩了嗎?
    一不小心就容易踩坑,裝修得不實用。1. 櫥櫃檯面高度不合適櫥櫃一般都是按照普遍的高度統一定製的,但其實每個人身高不同,應該要因人而異,適合的高度才能讓做飯的人更舒適更輕鬆,否則臺面太低就要彎腰,臺面太高又要抬著手臂幹活,都非常不舒服,所以定製臺面高度的時候要提前量好身高和尺寸,以定製出最合適的高度。
  • 蒂瑪秀兒:格局與信任是創始人最大的痛點,有些坑必須踩
    財務管理是企業中很重要的一節課,我訪談過一些企業,99%的創始人都說,企業的財務轉型升級能為幫企業帶來一定效益,降低成本。但我認為管理企業的過程中,更需要領導力的轉型,如果創始人的想法沒有達到一定的高度,身邊的CFO再怎麼推動,也難以改變創始人的格局。以我自己為例,我創辦過兩個公司。
  • 紅·Live直播 | 母乳餵養的坑,你踩過幾個?
    紅·Live直播 | 母乳餵養的坑,你踩過幾個?有這麼多的好處天然營養食物、容易消化吸收維護腸道健康、提高抗病能力降低感染風險、促進口腔發育益於智力發展、預防成年疾病母乳餵養給寶寶更多保護但是在進行母乳餵養時很多新手媽媽卻不斷踩坑
  • 家裝經驗血淚教訓,連明星都吐槽,這些坑你踩過多少?
    事後,鄭爽再次發文指出:「前幾天的裝修風波,讓我意識到一個問題,裝修是很多人的痛點」確實如此,生活中家裝被坑的事例數不勝數,材料質量差、裝修風格不搭、家電尺寸不合適、價格費用虛報……這些坑怕是每一個「裝修小白」都經歷過。
  • 陰陽師新手須知 少踩坑才能抽到ssr
    最近《陰陽師》手遊火得一塌糊塗,在我各種群、朋友圈紛紛討論起來,玄學也因此大火,得ssr的攻略也層出不窮,總結有幾點:畫圈不畫星 子時據說是靈氣最足的時辰(大約23點半-1點半) 每次抽卡間隔5秒 偶爾罵一下反而出好東西,但罵多了就全是r 其實全看臉,大家抽卡前記得洗手下面是我踩過的坑
  • 社保這些「坑」,你不要踩(二):員工可以承諾放棄繳納社保費?
    社保這些「坑」,你不要踩(一) | 試用期不必繳社保?這一期我們繼續避免踩「坑」!坑 2員工可以承諾放棄繳納社保費詳細解答《中華人民共和國社會保險法》第四條規定,中華人民共和國境內的用人單位和個人依法繳納社會保險費。第六十條規定,職工應當繳納的社會保險費由用人單位代扣代繳。