jquery 升级版本兼容问题整理

把 jQuery  1.3 (1.4以前)升级到最新jQuery版本之后,发现原本正常运作的效果出现许多异常,不是没反应就是反应变慢,于是展开漫长的除错大作战,为了避免以后忘记,还是记录下来比较好。

网路上写 jquery 各版本差异的文章很多,这里就不重复,直接用出错状况来记录。

1.状况:原先透过 AJAX 取得服务器回传资料来显示,在升级后不能显示或动作。
◦侦查:用 firebug 侦查不会出现错误讯息,捕捉回传讯息时会在 .error 显示 「Invalid JSON」。
◦问题: jquery 在 1.3 以前是用 javascript 的 eval 来解析 json 资料,而在 1.4 以后(包含 jquery 1.5 、 1.6、1.7)都改用更严格的方式来解析。
◦解决:回传的资料无论是键 key 或值 value 都必须用双引号「”」呈现(单引号 ‘ 不行) — 但数字除外。
举例来说:
原本回传
{ name:”王小明”, year:20}
在 1.3.x 以前是可以解析的。

但在 jquery 1.4 以后就要写成
{“name”:”王小明”, “year”:20}

2.状况:某些物件  bind() 、 unbind()  效果失效。
◦侦查:在浏览器开发工具中不会显示错误讯息。
◦问题:有几个物件透过 bind() 不同效果,例如

<div id=”123″>点这里会有效果</div>
$(‘#123’).bind(‘click’,function(){alert(‘Hello’);});
$(‘#123’).bind(‘mouseover’,function(){ $(this).css(‘color’,’red’);});
$(‘#123’).bind(‘click’,function(){ $(‘#other1’).hide();});

$(‘#other1’).cilick(function(){
$(‘#123’).unbind().bind(‘click’,function(){ $(‘#other2’).hide();});
});

希望出现点击 #123 时会出现两个效果–跳出提示、把另一个物件隐藏。
而点击  #other1 时会把 #123 最后 bind 的 #other1.hide() 效果移除,换上 bind #other2.hide();

在 jquery 1.3.2 中用 unbind 似乎只会移除最后 bind() 效果,不过因为在此桉中其它的 click 效果有用其它 jquery 封装所以这点需要确定,总之原先是正常 unbind 最后加的效果,但不影响其它 mousehove 、click 。

换成 jquery  1.7 后,採用 $(‘#123’).unbind() 会把 $(‘#123’) 上所有 bind() 效果一起移除。

◾方桉一:
var way1= function(){   $(‘#other1’).hide();  }
$(‘#123’).bind(‘click’,way1);
$(‘#123’).unbind(way1);
这样就不会影响其它 bind 效果。

◾方桉二:
如果 function 需要代变数又希望用直觉方式编码,方桉一就不怎么合用,这时候可以用事件命名空间来 bind。
$(‘#123’).bind(‘click.myEvent’,function(){$(‘#other1’).hide();});
$(‘#123’).unbind(‘click.myEvent’).bind(‘click.myEvent’,function(){$(‘#other2’).hide();});  //先移除原先效果再附上其它效果

这样 unbind 时就不会影响其它点击效果。

如果要移除所有自定点击效果可以这样写:.unbind(‘.myEvent’);

附带一提, jquery 1.7 建议改採 .on .off 来取代 .bind() .unbind()。

3.状况:改为 jquery 1.7 之后,检查 checked、selected 效果失效
◦侦查:浏览器无提示错误。
◦问题:checkedbox 用 if($(‘:checkbox’).attr(‘checked’)){alert(‘已选取’);}
在 jquery 1.6 以后改为
attr(‘checked’) 只能检查元件在载入页面时的值,之后要动态变动或取得变动后的状态,要用 prop(“checked”)才可以。
◦解决:改为
if( $(‘:checkbox’).prop(‘checked’) ){ alert(‘已选取’);  $(this).prop(‘checked’,false); }

问题解决!

4.状况:原本可以用 .css(‘background-color’:’none’)  或 .css(‘background-color’:”) 把背景色去除掉。现在不行!
◦解决:改用继承父元素即可。
.css(‘background-color’:’inherit’)

5.juqery radio写法的兼容性问题
老版本(1.3以前):
$(“[@name=’radio_name’][checked]”).val(),或者$(“[@name=’radio_name’]:checked”).val()
新版本:
$(“[name=’radio_name’][checked]”).val(),或者$(“input[name=’radio_name’]:checked”).val()

——————————我是分割线———————————————–

在jQuery 1.6筆記中有特別提到.prop()/.attr()的Break Change,將導致很多使用attr(“selected”), attr(“checked”)寫法的程式爆炸,必須修改後才能套用jQuery 1.6。很顯然,這個不向前相容的決定引起開發社群強烈反彈,即便此舉是往正確方向移動,但打破相容性影響重大,成千上萬的程式必須因此修改,產生可觀的升級成本,同時這也可能導致開發人員不願升級新版jQuery,於是jQuery開發團隊從善如流,決定回歸”先研究不傷身體,再講求效果”的精神,
在jQuery 1.6.1版調整.attr()存取邏輯,使其與1.5.2版本之前的做法相容。

這意味著:

$(“:checkbox”).attr(“checked”, true);
$(“option”).attr(“selected”, true);
$(“input”).attr(“readonly”, true);
$(“input”).attr(“disabled”, true);
if ( $(“:checkbox”).attr(“checked”) ) { /* Do something */ }

等寫法在jQuery 1.6.1裡可以繼續順利運作,但仍有些建議:

  1. $(window).attr(), $(document).attr()建議改為$(windows).prop(), $(document).prop(),因為window及document理論上無從加上HTML Attribute,雖然jQuery 1.6.1在內部會偷偷改用.prop(),畢竟語意不合邏輯,應該避免。
  2. 在HTML語法<input type=”checkbox” checked=”checked” />中,checked Attribute只會在一開始將checked Property設成true,後續的狀態變更及儲存都是透過checked Property。換句話說,checked Attribute只影響初值,之後應以checked Property為準。基於這個理由,$(“:checkbox”).prop(“checked”, true)會比$(“:checkbox”).attr(“checked”, true)來得合理。雖然jQuery 1.6.1已讓$(“:checkbox”).attr(“checked”, true)也具有變更checked Property的能力,但prop()確實比attr()寫法更吻合背後的實際運作。
    適用此點的Boolean屬性包含了: autofocus, autoplay, async, checked, controls, defer, disabled, hidden, loop, multiple, open, readonly, required, scoped, selected

另外,jQuery Team提供一張DOM元素屬性適用attr()/prop()的對照表:

Attribute/Property .attr() .prop()
accesskey
align
async
autofocus
checked
class
contenteditable
defaultValue
draggable
href
id
label
location *
multiple
nodeName
nodeType
readOnly
rel
selected
selectedIndex
src
style
tabindex
tagName
title
type
width **

結論: 針對Boolean型別屬性或是沒有對應HTML Attribute者(例如: window.location)建議使用.prop(),其餘則可使用.attr()。[註: 紅色部分為可支援,但不建議使用]

jquery 1.7
新的事件 APIs: .on() and .off()
之前绑定事件使用:
$(‘a’).bind(‘click’, myHandler);
jquery 1.7就可以使用下面代码:
$(‘a’).on(‘click’, myHandler);
在取消绑定事件
$(‘a’).unbind(‘click’, myHandler);
$(‘a’).off(‘click’, myHandler);
被删除的方法:
1、event.layerX and event.layerY
2、jQuery.isNaN()
3、jQuery.event.proxy()

参考文章:
http://api.jquery.com/category/version/
http://blog.jquery.com/2012/08/09/jquery-1-8-released/
http://mr.nio.tw/contentA.php?id=1317
http://blog.darkthread.net/post-2011-05-13-jquery-1-6-1.aspx

Leave a Reply