自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

經(jīng)典推送:針對(duì)jQuery升級(jí)踩坑大全

開發(fā) 前端
前段時(shí)間我就主導(dǎo)了這件事情,把公司里我們組負(fù)責(zé)的項(xiàng)目jQuery版本從1.4.2升級(jí)到了jQuery 1.11.3。jQuery官方也為類似升級(jí)工作提供了jQuery Migrate插件。

背景


jQuery想必各個(gè)web工程師都再熟悉不過(guò)了,不過(guò)現(xiàn)如今很多網(wǎng)站還采用了很古老的jQuery版本。其實(shí)如果早期版本使用不當(dāng),可能會(huì)有 DOMXSS漏洞,非常建議升級(jí)到j(luò)Query 1.9.x或以上版本。前段時(shí)間我就主導(dǎo)了這件事情,把公司里我們組負(fù)責(zé)的項(xiàng)目jQuery版本從1.4.2升級(jí)到了jQuery 1.11.3。jQuery官方也為類似升級(jí)工作提供了jQuery Migrate插件。

言歸正傳。

坑從何處來(lái)


jQuery 1.11.3是1.x時(shí)代的最后一個(gè)版本(作者更新:2016年1月8日,jQuery 1.12.0上線,jQuery 1.11.3不再是1.x時(shí)代最后一個(gè)版本了),由于我的部門項(xiàng)目已經(jīng)有一定年頭了,當(dāng)時(shí)還是采用的jQuery 1.4.2,這次升級(jí)步子邁得算是比較大。早期時(shí)候jQuery的很多寫法,在新版本中已經(jīng)被廢棄,亦或者有些不規(guī)范的寫法,當(dāng)時(shí)版本還能支持,但是現(xiàn)在 已經(jīng)不支持。更糟糕的情況是,新版本還支持,但是功能已經(jīng)和以前不一樣了……這種情況連個(gè)錯(cuò)都不會(huì)報(bào),需要深入到代碼邏輯里面去看。

jQuery官方推薦了jQuery Migrate 庫(kù)來(lái)解決jQuery升級(jí)問(wèn)題。不過(guò)一直采用這個(gè)庫(kù)終究不是長(zhǎng)久之計(jì),開發(fā)中建議使用jQuery Migrate的開發(fā)版,可以在瀏覽器控制臺(tái)上打印出來(lái)不兼容的地方詳細(xì)信息。需要注意的是開發(fā)中一定要使用jQuery Migrate的開發(fā)版,因?yàn)閴嚎s版的是不會(huì)在控制臺(tái)給出警告的……把jQuery Migrate的庫(kù)緊跟在jQuery庫(kù)后面引用即可:

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

等升級(jí)完畢,確定沒問(wèn)題了之后,再將jQuery Migrate庫(kù)去掉就可以了。根據(jù)個(gè)人經(jīng)驗(yàn),下面我把坑分成 常見坑,少見坑兩類來(lái)論述。

常見坑


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

jQuery Migrate庫(kù)對(duì)此錯(cuò)誤也在控制臺(tái)有相應(yīng)的警告:

  1. JQMIGRATE: jQuery.fn.live() is deprecated 

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

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

乍一看,中括號(hào)里面的參數(shù)可以省略掉,倆函數(shù)不是一模一樣么?于是天真地把函數(shù)名live直接替換成on,大部分時(shí)候,這么做好像沒有引起任何異常。但是如果在你調(diào)用on函數(shù)的時(shí)候,前面的$(selector)在當(dāng)前的網(wǎng)頁(yè)上根本不匹配任何元素(該元素可能是后面的代碼才加到DOM里的),那是不會(huì)綁定成功的。事實(shí)上,live函數(shù)將$(selector)代理到了document元素上,這個(gè)元素是肯定存在的,所以不會(huì)出現(xiàn)類似情況。正確的替換方法應(yīng)該是:

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

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

jQuery Migrate對(duì)此錯(cuò)誤的警告是:

  1. JQMIGRATE: jQuery.fn.die() is deprecated 

這個(gè)方法和前面的live剛好反過(guò)來(lái),取消事件處理函數(shù)的綁定。新版本中應(yīng)該使用off函數(shù)代替之,替換方式類似。

3. 使用了被廢棄的jQuery.fn.toggle函數(shù)

jQuery Migrate對(duì)此錯(cuò)誤的警告是:

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

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

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

jQuery Migrate對(duì)此錯(cuò)誤的警告是

  1. JQMIGRATE: jQuery.browser is deprecated 

在前端開發(fā)中我們經(jīng)常要根據(jù)不同的瀏覽器版本做出不同的處理,jQuery.browser本來(lái)是通過(guò)瀏覽器的userAgent字段來(lái)提取瀏覽器相關(guān)信息的。新版本中已經(jīng)將其廢棄,而是建議使用特征檢測(cè)的方法去判斷,并且給了一個(gè)Modernizr庫(kù)作為推薦。不過(guò),改成這個(gè)庫(kù)可能改動(dòng)成本有點(diǎn)大,如果你還是想沿用jQuery.browser的思路的話,可以自己去實(shí)現(xiàn)一下它。例如,判斷是不是IE瀏覽器,可以用

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

即自己手動(dòng)獲取userAgent字段,并且做一個(gè)正則表達(dá)式匹配。其他瀏覽器思路類似,都是對(duì)navigator.userAgent做一個(gè)正則匹配。

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

在jQuery Migrate中,出現(xiàn)以下三種警告中的任何一種,都是屬于這個(gè)錯(cuò)誤:

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

這個(gè)錯(cuò)誤還是蠻值得注意的,因?yàn)槲覀兾恼麻_頭所說(shuō)的jQuery低版本有XSS漏洞,其實(shí)就是和這個(gè)錯(cuò)誤有關(guān)系。在javascript中我們經(jīng)常會(huì)直接將一段html格式的字符串寫在jQuery引用里面,比如$('<div></div>')。按照新版本的jQuery要求,這段html格式的字符串必須是以左尖括號(hào)(小于號(hào))開頭,其他字符都不可以。以下幾種寫法,都是錯(cuò)誤的:

1. $(" <div></div>"); //錯(cuò)誤,字符串最開頭有一個(gè)空格,不是以小于號(hào)'<'開頭的 2. $("<div></div>test"); //不標(biāo)準(zhǔn),html標(biāo)簽結(jié)束后后面還有多余的"test",它會(huì)被忽略 3. $("#<div></div>); //錯(cuò)誤,以井號(hào)開頭并且后面并不是一個(gè)css選擇器

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

6. jQuery.fn.attr方法的錯(cuò)誤使用(這是個(gè)非常易犯的錯(cuò)誤?。?/strong>

jQuery Migrate中,關(guān)于attr方法的警告有以下這些:

  1.  JQMIGRATE: jQuery.fn.attr('value', val) no longer sets properties
  2. JQMIGRATE: jQuery.fn.attr('value') no longer gets properties
  3. JQMIGRATE: jQuery.fn.attr('checked') may use property instead of attribute
  4. JQMIGRATE: jQuery.fn.attr( props, pass ) is deprecated

實(shí)踐中我發(fā)現(xiàn),早期寫的代碼里面,獲取一個(gè)input輸入表單的值時(shí),是怎么獲取的呢?$('input').attr('value');又是怎么設(shè)置的呢?$('input').attr('value', 'helloworld')。這在新版本中都是不正確的!正確的做法應(yīng)該是

  1. $('input').val(); //獲取input表單現(xiàn)在所輸入的值 
  2. $('input').val('helloworld'); //設(shè)置input表單輸入的值 

到底是獲取還是設(shè)置,只取決于調(diào)用val方法時(shí)有沒有帶著參數(shù)。

如果你想手動(dòng)設(shè)置單選框(例如<input type="radio" >)被選中,應(yīng)該怎么設(shè)置呢?老的代碼里面可能會(huì)看到這樣 $('input').attr('checked', true)或者$('input').attr('checked', 'checked')。這些現(xiàn)在也都是不正確的!正確的做法應(yīng)該是

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

這是從jQuery 1.6版本開始使用的寫法。如果設(shè)置disabled和selected屬性,也是使用prop方法。那到底什么時(shí)候使用attr方法呢??jī)烧叩膮^(qū)別 是:prop設(shè)置的是某元素固有的屬性,而attr設(shè)置的是寫在html標(biāo)簽上的自定義屬性。舉個(gè)例子:

  1. <input type="checkbox" checked="checked" haha="hello" > 
  2. var v1 = $('input').prop("checked"); //返回true/false,是否被選中,隨狀態(tài)改變而改變 
  3. var v2 = $('input').attr("checked"); //返回"checked",這是你設(shè)置在標(biāo)簽上的,不會(huì)變 
  4. var v3 = $('input').attr("haha"); //返回"hello",自定義屬性 
  5. var v4 = $('input').prop("haha"); //返回undefined,根本沒有這個(gè)固有屬性 

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

7. 向$.parseJSON傳入了非法的參數(shù)

在jQuery Migrate中,該錯(cuò)誤產(chǎn)生如下警告

JQMIGRATE: jQuery.parseJSON requires a valid JSON string

jQuery之所以改這個(gè)接口,是為了和瀏覽器自帶的JSON.parse接口對(duì)齊,從jQuery 1.9開始生效。這個(gè)問(wèn)題常見于AJAX接收服務(wù)端返回值的時(shí)候。服務(wù)端可能返回一個(gè)空字符串,這時(shí)候調(diào)用該接口會(huì)產(chǎn)生錯(cuò)誤。必須向$.parseJSON傳入合法的JSON字符串。修正方法如下:

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

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

在jQuery Migrate中該錯(cuò)誤產(chǎn)生如下警告

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

在注冊(cè)事件處理函數(shù)時(shí),'hover'以前可以看作是'mouseenter mouseleave'兩個(gè)事件的別稱。目前已經(jīng)將該別稱去掉了,所以代碼中請(qǐng)用'mouseenter mouseleave'替換之。

9. jQuery.fn.andSelf已經(jīng)被替換,不能再使用

jQuery Migrate中是這樣的警告:

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

兩個(gè)函數(shù)功能是完全一樣的,可以直接替換。

以上,就是在jQuery升級(jí)中常見的問(wèn)題,當(dāng)然,本著精益求精的精神,我們還是需要研究一下不常見的問(wèn)題是什么樣子的。需要指出的是:下面的問(wèn)題在我的實(shí)際項(xiàng)目中從來(lái)沒有碰到過(guò),比較少見,但也無(wú)法保證一定不會(huì)出現(xiàn)在你的項(xiàng)目中,僅供感興趣的程序員們參考吧。

少見坑


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

這個(gè)錯(cuò)誤的觸發(fā)方式非常簡(jiǎn)單,直接把html頁(yè)面最頂端的<!DOCTYPE html>標(biāo)簽刪掉就可以了。瀏覽器怪異模式是為了兼容老古董網(wǎng)頁(yè)而設(shè)計(jì)的,詳情可參考這篇文章:鏈接。我想現(xiàn)在的WEB程序員應(yīng)該不會(huì)傻到不寫DOCTYPE,也很少使用這種模式下的瀏覽器吧。

jQuery Migrate展示的錯(cuò)誤警告如下:

2. AJAX全局事件必須綁定到document節(jié)點(diǎn)上

jQuery Migrate中的警告如下:

  1. JQMIGRATE: AJAX events should be attached to document: ajaxStart 

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

  1. $("#status").ajaxStart(function(){ $(this).text("Ajax started"); }); 修改為 
  2. $(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屬性,你可以直接把文本框改成單選框,改成多選框等等。雖然我感覺這是一種并不算優(yōu)雅的行為,但是很多瀏覽器都是支持這么做的,除了IE6/7/8。建議在實(shí)際中也是少用這個(gè)功能為好。

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

在jQuery Migrate中是這樣的警告:

  1. JQMIGRATE: jQuery.clean() is deprecated
  2. JQMIGRATE: jQuery.event.handle is undocumented and deprecated
  3. JQMIGRATE: jQuery.attrFn is deprecated
  4. JQMIGRATE: Use of jQuery.fn.data('events') is deprecated
  5. JQMIGRATE: Global events are undocumented and deprecated

如果你在自己的代碼中使用過(guò)這五個(gè)接口,那確實(shí)是仔細(xì)研究過(guò)jQuery源代碼 的高人啊。因?yàn)檫@五個(gè)接口從來(lái)沒有出現(xiàn)在jQuery的官方文檔中,并且有些在后續(xù)版本中已經(jīng)刪除,可謂來(lái)無(wú)影去無(wú)蹤。看源代碼的話在早期版本有機(jī)會(huì)找到 他們的存在,但是并不建議使用。建議采用其他方法實(shí)現(xiàn)相應(yīng)的功能。什么?你不知道這五個(gè)函數(shù)是什么功能?那最好了,你現(xiàn)在也不需要知道了……

5. 使用了過(guò)時(shí)的$.sub()方法

jQuery Migrate中對(duì)本問(wèn)題的警告如下:

  1. JQMIGRATE: jQuery.sub() is deprecated 

這個(gè)接口非常簡(jiǎn)單,不接受任何參數(shù)。它用來(lái)創(chuàng)建一個(gè)jQuery的副本。該方法在jQuery 1.7版本開始就已經(jīng)不再使用。

6. 使用了過(guò)時(shí)的jQuery.fn.error方法

jQuery Migrate中對(duì)本問(wèn)題的警告如下:

  1. JQMIGRATE: jQuery.fn.error() is deprecated 

在jQuery中,error也是和click一樣的事件。注冊(cè)該事件的處理函數(shù),以前是$(selector).error(function(){}),現(xiàn)在已經(jīng)被廢棄,可以使用$(selector).on('error', function(){})來(lái)替代。

示例代碼


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

  1. <!-- filename : index.html --> 
  2. <!--<!DOCTYPE html>--> //keng0 怪異模式 
  3. <html> 
  4.     <head> 
  5.         <meta charset="utf-8" /> 
  6.         <title>jQuery升級(jí)踩坑大全</title> 
  7.         <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.4.min.js" ></script> 
  8.         <script type="text/javascript" src="http://code.jquery.com/jquery-migrate-1.2.1.js" ></script> 
  9.     </head> 
  10.     <body> 
  11.         <div class="test" id="a">a</div> 
  12.         <input type="radio" id="b" value="b" /> 
  13.         <input type="radio" id="c" value="c" /> 
  14.         <div id="d" value="d">test</div> 
  15.         <script type="text/javascript"> 
  16.             //開始踩坑 
  17.  
  18.             //使用被廢棄分$.attrFn方法 
  19.             var keng1 = $.attrFn || {}; 
  20.              
  21.             //該函數(shù)在jQuery內(nèi)部調(diào)用,真實(shí)項(xiàng)目中從未見過(guò),可忽略,這里只是為了觸發(fā)一下錯(cuò)誤警告 
  22.             var keng2 = $.attr($("#a"), "class""xxx", true); 
  23.              
  24.             //IE6、7、8中不支持改變輸入框的類型 
  25.             var keng3 = $("input#b").attr("type", "text"); 
  26.              
  27.             //在該使用prop的地方使用了attr 
  28.             var keng4 = $("input#c").attr("checked", true); 
  29.              
  30.             //使用attr獲取property的值,正確的是應(yīng)該使用 .val() 
  31.             var keng5 = $("div#d").attr("value"); 
  32.              
  33.             //使用attr設(shè)置property的值,正確的是應(yīng)該使用 .val('somevalue') 
  34.             var keng6 = $("div#d").attr("value", "abcd"); 
  35.              
  36.             //html字符串必須以'<'開頭(下面這個(gè)是以空格開頭) 
  37.             var keng7 = $(" <div></div>"); 
  38.              
  39.             //最后一個(gè)tag后面還有多余字符串 
  40.             var keng8 = $("<div></div>abc"); 
  41.  
  42.             //html字符串不可以以井號(hào)‘#’開頭 
  43.             try{ 
  44.                 var keng9 = $("#<div></div>"); 
  45.             }catch(e){ 
  46.                 console.error(e); 
  47.             } 
  48.          
  49.             //$.parseJSON的參數(shù)必須是合法的JSON字符串 
  50.             var keng10 = $.parseJSON(undefined); 
  51.              
  52.             //使用被廢棄的$.browser 
  53.             var keng11 = $.browser; 
  54.              
  55.             //使用被廢棄的$.sub 
  56.             var keng12 = $.sub(); 
  57.              
  58.             $("#c").on("click", function(){}); 
  59.             var keng13 = $("#c").data("events"); 
  60.              
  61.             //調(diào)用了已經(jīng)不再使用的函數(shù)andSelf,該函數(shù)已經(jīng)被addBack替代 
  62.             var keng14 = $("#c").nextAll().andSelf(); 
  63.  
  64.             //使用被廢棄的$.clean方法 
  65.             try{ 
  66.                 var keng15 = $.clean(); 
  67.             }catch(e){ 
  68.                 console.error(e); 
  69.             } 
  70.              
  71.             //"hover"字符串注冊(cè)事件已經(jīng)被拆成"mouseenter"和"mouseleave"兩個(gè) 
  72.             var keng16 = $("#d").on("hover", function(){/*some code*/}); 
  73.              
  74.             //jQuery.event.handle并沒有收錄到官方的API中,新版本已經(jīng)被移除 
  75.             var keng17 = function(){ 
  76.                 $.event.handle.apply(this, arguments); 
  77.             }; 
  78.              
  79.             //全局AJAX事件處理必須綁定到document對(duì)象上 
  80.             var keng18 = $("#c").ajaxStart(function(){}); 
  81.              
  82.             //使用了被廢棄的error方法 
  83.             var keng19 = $("#c").error(function(){}); 
  84.  
  85.             //使用了被廢棄的toggle方法 
  86.             var keng20 = $("#d").toggle(function(){/*some code*/}, function(){/*some code*/}); 
  87.  
  88.             //使用了被廢棄的live方法,應(yīng)該使用on方法替代之 
  89.             var keng21 = $("#a").live("click", function(){/*some code*/}); 
  90.  
  91.             //使用了被廢棄的die方法,應(yīng)該使用off方法替代之 
  92.             var keng22 = $("#a").die("click"); 
  93.  
  94.             //使用了全局事件函數(shù),目前全局事件只支持AJAX那幾個(gè),其他全局事件都不支持 
  95.             var keng23 = $.event.trigger("click");         
  96.  
  97.         </script> 
  98.     </body> 
  99. </html>

 

 

責(zé)任編輯:王雪燕 來(lái)源: 博客園
相關(guān)推薦

2023-02-20 08:11:04

2023-01-18 23:20:25

編程開發(fā)

2020-09-15 08:46:26

Kubernetes探針服務(wù)端

2017-10-24 13:02:29

2017-05-05 08:12:51

Spark共享變量

2021-10-28 19:10:02

Go語(yǔ)言編碼

2024-04-10 08:39:56

BigDecimal浮點(diǎn)數(shù)二進(jìn)制

2021-09-03 11:15:18

場(chǎng)景sql配置

2024-04-01 08:05:27

Go開發(fā)Java

2023-04-26 11:29:58

Jenkins版本Java 11

2018-10-31 11:30:28

Redis數(shù)據(jù)分布式鎖

2023-09-22 11:29:11

JavasubList

2017-07-17 15:46:20

Oracle并行機(jī)制

2021-05-27 22:46:00

Nacos Clien版本Nacos

2021-10-15 06:49:37

MySQL

2022-11-18 07:34:12

Docker項(xiàng)目目錄

2024-10-09 08:09:11

2010-05-25 13:34:18

MySQL命令

2023-06-30 08:10:14

JavaBigDecimal

2025-04-29 10:17:42

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)