>  기사  >  웹 프론트엔드  >  jQuery 버전을 업그레이드할 때 주의해야 할 점은 무엇인가요?

jQuery 버전을 업그레이드할 때 주의해야 할 점은 무엇인가요?

php中世界最好的语言
php中世界最好的语言원래의
2018-04-23 15:48:273803검색

이번에는 jQuery 버전 업그레이드 시 주의사항에 대해 알려드리겠습니다. jQuery 버전 업그레이드 시 주의사항은 무엇인가요? 다음은 실제 사례입니다.

배경

----------------------------------------------- --- ---------------------

jQuery는 모든 웹 엔지니어에게 친숙할 것입니다. 하지만 이제는 오늘날 많은 웹사이트에서는 여전히 매우 오래된 버전의 jQuery를 사용하고 있습니다. 실제로 이전 버전을 부적절하게 사용할 경우 DOMXSS 취약점이 있을 수 있으므로 jQuery 1.9.x 이상으로 업그레이드하는 것이 좋습니다. 얼마 전 제가 이 문제를 주도적으로 맡아 우리 팀이 회사에서 담당하고 있는 프로젝트의 jQuery 버전을 1.4.2에서 jQuery 1.11.3으로 업그레이드한 적이 있습니다. jQuery는 유사한 업그레이드 작업을 위해 공식적으로 jQuery Migrate 플러그인도 제공합니다.

사업으로 돌아갑니다.

구덩이는 어디서 오는 걸까요

----------------------------------------- - --------------------------

jQuery 1.11.3이 1입니다. x 시대 마지막 버전(작성자 업데이트: jQuery 1.12.0은 2016년 1월 8일에 출시되었으며 jQuery 1.11.3은 더 이상 1.x 시대의 마지막 버전이 아닙니다). 당시에는 아직 jQuery 1.4.2를 사용하고 있었지만 이번 업그레이드는 비교적 큰 진전이었습니다. 초기의 많은 jQuery 작성 방법이 새 버전에서 폐기되었거나, 당시 버전에서는 여전히 지원하지만 더 이상 지원되지 않는 일부 비표준 작성 방법이 있습니다. 더 나쁜 점은 새 버전에서는 여전히 지원하지만 기능이 이전과 다르다는 것입니다. 이 경우 오류조차 보고되지 않으며 확인하려면 코드 로직에 깊이 들어가야 합니다.

jQuery는 jQuery 업그레이드 문제를 해결하기 위해 jQuery Migrate 라이브러리를 공식적으로 권장합니다. 그러나 이 라이브러리를 항상 사용하는 것은 장기적인 해결책이 아닙니다. 개발 중에는 브라우저 콘솔의 비호환성에 대한 자세한 정보를 인쇄할 수 있는 jQuery Migrate 개발 버전을 사용하는 것이 좋습니다. 압축된 버전은 콘솔에 경고를 표시하지 않기 때문에 개발 중에는 jQuery Migrate 개발 버전을 사용해야 한다는 점에 유의해야 합니다... jQuery 라이브러리 바로 뒤에 jQuery Migrate 라이브러리를 인용하면 됩니다:

db99534a710f711a5502883b79acdbd1/05034471df6398a62d5708f78b78e0ac/jquery-1.11.3.js">2cacc6d41bbb37262a98f745aa00fbf0
db99534a710f711a5502883b79acdbd1/05034471df6398a62d5708f78b78e0ac/jquery-migrate-1.2.1.js">2cacc6d41bbb37262a98f745aa00fbf0

등. 업그레이드가 완료되었고 문제가 없다고 확신한다면 jQuery Migrate 라이브러리를 제거하기만 하면 됩니다. 개인적인 경험을 바탕으로 아래의 함정을 일반적인 함정과 드문 함정이라는 두 가지 범주로 나누어 논의하겠습니다.

일반적인 함정

------------------------------- ------ -----------------------

1. jQuery.fn. 라이브 메소드

jQuery Migrate 라이브러리에도 이 오류에 대한 해당 경고가 콘솔에 있습니다.

JQMIGRATE: jQuery.fn.live()는 더 이상 사용되지 않습니다.
라이브 메소드의 원래 기능은 이벤트를 설정하는 것입니다. 프록시입니다. 이 방법은 jQuery 1.7 이후입니다. 사용을 권장하지 않으며 jQuery.fn.on 함수로 대체됩니다. 인터페이스는 다음과 같습니다.

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

얼핏 보면 대괄호 안의 매개변수는 생략될 수 있습니다. 두 기능은 완전히 동일하지 않나요? 그래서 나는 순진하게 함수 이름을 on으로 바꾸었습니다. 대부분의 경우 이로 인해 예외가 발생하지 않는 것 같습니다. 그러나 on 함수를 호출할 때 이전 $(selector)가 현재 웹 페이지의 어떤 요소와도 일치하지 않으면(이 요소는 이후 코드에서 DOM에 추가될 수 있음) 바인딩이 성공하지 못합니다. 실제로 라이브 함수는 $(selector)를 문서 요소로 프록시하므로 이 요소는 확실히 존재하므로 비슷한 상황이 발생하지 않습니다. 올바른 교체 방법은 다음과 같습니다.

$(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

이 방법은 이전 라이브와 정반대입니다. 취소 이벤트 처리함수 바인딩. 새 버전에서는 대신 off 기능을 사용해야 하며 교체 방법은 비슷합니다.

3 버려진 jQuery.fn.toggle 함수가 사용됩니다.

jQuery Migrate에서 이 오류에 대한 경고는 다음과 같습니다.

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

초기 jQuery에는 토글이라는 함수가 두 개 있는데, 하나는 요소 표시 및 숨기기, 함수 제어에 사용됩니다. 이 목적을 위해 jQuery에는 여전히 존재합니다. 다른 하나는 위에서 언급한 버려진 토글 함수로, 요소를 클릭하면 두 함수가 번갈아 실행됩니다. 동일한 이름을 가진 이 두 함수의 기능은 매우 다릅니다. 오해를 일으키지 않기 위해 jQuery 1.8에서는 더 이상 사용하지 않는 것이 좋습니다. 대체 방법은 두 함수를 한 함수의 if-else 섹션으로 병합한 다음, 클릭할 때마다 실행할 섹션을 제어하기 위해 부울 변수를 직접 설정하는 것입니다.

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中,出现以下三种警告中的任何一种,都是属于这个错误:

JQMIGRATE: $(html) HTML strings must start with &#39;<&#39; character
JQMIGRATE: $(html) HTML text after last tag is ignored
JQMIGRATE: HTML string cannot start with a &#39;#&#39; character

这个错误还是蛮值得注意的,因为我们文章开头所说的jQuery低版本有XSS漏洞,其实就是和这个错误有关系。在javascript中我们经常会直接将一段html格式的字符串写在jQuery引用里面,比如$('e388a4556c0f65e1904146cc1a846bee94b3e26ee717c64999d7867364b1b4a3')。按照新版本的jQuery要求,这段html格式的字符串必须是以左尖括号(小于号)开头,其他字符都不可以。以下几种写法,都是错误的:

$(" <p></p>"); //错误,字符串最开头有一个空格,不是以小于号&#39;<&#39;开头的
$("<p></p>test"); //不标准,html标签结束后后面还有多余的"test",它会被忽略
$("#<p></p>); //错误,以井号开头并且后面并不是一个css选择器

这一点在书写的时候注意一下就可以了,其实还是很容易避免的。其中第三种错误其实就不仅仅是警告了,jQuery会直接抛出一个错误,停止javascript代码的继续执行。一般情况以井号开头,例如$("#test"),其实就是一个普通的选择器,但是上面例子中后面又夹杂着html字符串,这会被jQuery判断为潜在的XSS攻击。

6. jQuery.fn.attr方法的错误使用(这是个非常易犯的错误!)

jQuery Migrate中,关于attr方法的警告有以下这些:

JQMIGRATE: jQuery.fn.attr(&#39;value&#39;, val) no longer sets properties
JQMIGRATE: jQuery.fn.attr(&#39;value&#39;) no longer gets properties
JQMIGRATE: jQuery.fn.attr(&#39;checked&#39;) may use property instead of attribute
JQMIGRATE: jQuery.fn.attr( props, pass ) is deprecated

实践中我发现,早期写的代码里面,获取一个input输入表单的值时,是怎么获取的呢?$('input').attr('value');又是怎么设置的呢?$('input').attr('value', 'helloworld')。这在新版本中都是不正确的!正确的做法应该是

$('input').val(); //获取input表单现在所输入的值
$('input').val('helloworld'); //设置input表单输入的值

到底是获取还是设置,只取决于调用val方法时有没有带着参数。

如果你想手动设置单选框(例如70399a5e80bd8088d4fe7a1486dc379b)被选中,应该怎么设置呢?老的代码里面可能会看到这样 $('input').attr('checked', true)或者$('input').attr('checked', 'checked')。这些现在也都是不正确的!正确的做法应该是

$(&#39;input&#39;).prop(&#39;checked&#39;, true); //把单选框设为选中状态
$(&#39;input&#39;).prop(&#39;checked&#39;); //获取单选框是不是被选中了,返回true或false

这是从jQuery 1.6版本开始使用的写法。如果设置disabled和selected属性,也是使用prop方法。那到底什么时候使用attr方法呢?两者的区别是:prop设置的是某元素固有的属性,而attr设置的是写在html标签上的自定义属性。举个例子:

45ec6edb2d9d76ce07367010c4d75f57
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: &#39;hover&#39; pseudo-event is deprecated, use &#39;mouseenter mouseleave&#39;

在注册事件处理函数时,'hover'以前可以看作是'mouseenter mouseleave'两个事件的别称。目前已经将该别称去掉了,所以代码中请用'mouseenter mouseleave'替换之。

9. jQuery.fn.andSelf已经被替换,不能再使用

jQuery Migrate中是这样的警告:

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

两个函数功能是完全一样的,可以直接替换。

以上,就是在jQuery升级中常见的问题,当然,本着精益求精的精神,我们还是需要研究一下不常见的问题是什么样子的。需要指出的是:下面的问题在我的实际项目中从来没有碰到过,比较少见,但也无法保证一定不会出现在你的项目中,仅供感兴趣的程序员们参考吧。

少见坑

--------------------------------------------------------------------------------

1. jQuery不兼容浏览器的怪异模式

这个错误的触发方式非常简单,直接把html页面最顶端的8b05045a5be5764f313ed5b9168a17e6标签删掉就可以了。浏览器怪异模式是为了兼容老古董网页而设计的,详情可参考这篇文章:链接。我想现在的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&#39;t change the &#39;type&#39; 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中是这样的警告:

JQMIGRATE: jQuery.clean() is deprecated
JQMIGRATE: jQuery.event.handle is undocumented and deprecated
JQMIGRATE: jQuery.attrFn is deprecated
JQMIGRATE: Use of jQuery.fn.data(&#39;events&#39;) is deprecated
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键打开控制台,你就可以看到壮观宏伟的控制台警告了^_^

2ecd5497ab3e185051c2e8f4b729bd8d6bcb2e73c7c27ed4e5f30ea75c07bd3c--> //keng0 怪异模式
100db36a723c770d327fc0aef2ce13b1
93f0f5c25f18dab9d176bd4f6de5d30e
8492913265be600fb60cbb94f9489386
b2386ffb911b14667cb8f0f91ea547a7jQuery升级踩坑大全6e916e0f7d1e588d4f442bf645aedb2f
a00ff767ab7924c8175b887f7becf7dc2cacc6d41bbb37262a98f745aa00fbf0
8b813f2be3be186aca6635a59bf81c822cacc6d41bbb37262a98f745aa00fbf0
9c3bca370b5104690d9ef395f2c5f8d1
6c04bd5ca3fcae76e30b72ad730ca86d
c4a6aa43c5f22940a761fb7454a53467a94b3e26ee717c64999d7867364b1b4a3
07594f6363763abb42a696b9bea48776
642974f256be81137dd77a8ac5f2805d
c97f9cbde1fc09cf45a4717cb0fd699ftest94b3e26ee717c64999d7867364b1b4a3
8019067d09615e43c7904885b5246f0a
//开始踩坑
//使用被废弃分$.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 = $("p#d").attr("value");
//使用attr设置property的值,正确的是应该使用 .val('somevalue')
var keng6 = $("p#d").attr("value", "abcd");
//html字符串必须以'<'开头(下面这个是以空格开头)
var keng7 = $(" e388a4556c0f65e1904146cc1a846bee94b3e26ee717c64999d7867364b1b4a3");
//最后一个tag后面还有多余字符串
var keng8 = $("e388a4556c0f65e1904146cc1a846bee94b3e26ee717c64999d7867364b1b4a3abc");
//html字符串不可以以井号‘#'开头
try{
var keng9 = $("#e388a4556c0f65e1904146cc1a846bee94b3e26ee717c64999d7867364b1b4a3");
}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"); 
2cacc6d41bbb37262a98f745aa00fbf0
36cc49f0c466276486e50c850b7e4956
73a6ac4ed44ffec12cee46588e518a5e

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

怎样使jQuery延迟执行

使用JQuery操作Ajax(附案例)

위 내용은 jQuery 버전을 업그레이드할 때 주의해야 할 점은 무엇인가요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.