升級到j(luò)Query?3.6.1遇見的一些坑以及應(yīng)對辦法
前言
項目因安全問題(jquery 早期版本存在XSS 漏洞),需要整體將 jQuery 從 1.7.2 升級到 3.6.1 。早前就因為 jQuery 的版本兼容性不佳,因此對于版本升級的事情,能拖則拖。但升級的事情,總歸是要做的,何況項目上因為甲方重視安全性,對于中等風(fēng)險的安全也必須解決、規(guī)避,因此這回是硬著頭皮上了。
第一階段的問題,就是各種不兼容,各種不順。好在同事方法多,路子廣,找到了一個 jquery-migrate-3.4.0.js 文件,專治新舊版本兼容的 包,解決了大多數(shù)的問題。UI 界面總算能跑起來,能看得著了。
但是接下來,陸續(xù)遇到了幾個問題:
問題一:curCSS 方法找不到問題
解決方法:
jQuery.curCSS = function(element, prop, val) {
return jQuery(element).css(prop, val);
};問題二:UI 布局錯誤,多處動態(tài)計算 div 占用的寬度、高度 進行自適應(yīng)布局的頁面都拉跨了。
仔細(xì)分析后發(fā)現(xiàn),罪魁禍?zhǔn)壮霈F(xiàn)在 outerWidth 和 outerHeight 方法上。
這兩個方法,老版本 jquery (以 1.7.2 為例),例如調(diào)用 $("body").outerWidth() ,是可以返回整數(shù)值的。但是新版的方法,如果不帶參數(shù),則返回 元素的 jQuery 對象。 而由于程序?qū)⒅暈?int 參與計算,因此導(dǎo)致后續(xù)計算錯誤,界面布局拉跨也就難免了。
另外,老版本 jQuery 對于查找器搜索不到的情況,比如 $("#不存在的id").outerWidth() 是會返回 0 的,因為將一個不存在的元素的寬度視為0,也算是容錯的,但是新版本在這種情況下,直接返回 undefined,這也會造成一些代碼上的問題。
OK,知道原因,就可以有解決方案,如下:
var oldOuterWidth = jQuery.fn.outerWidth;
jQuery.fn.outerWidth =function( ) {
if (arguments.length <= 0) {
arguments[0] = false;
arguments.length = 1;
}
var result = oldOuterWidth.apply( this, arguments ) ;
return result === undefined ? 0 : result;
};
var oldOuterHeight = jQuery.fn.outerHeight;
jQuery.fn.outerHeight =function( ) {
if (arguments.length <= 0) {
arguments[0] = false;
arguments.length = 1;
}
var result = oldOuterHeight.apply( this, arguments );
return result === undefined ? 0 : result;
}; 問題三、添加 html 內(nèi)容 出錯,頁面元素 層次錯亂。
比如,有以下代碼:
$("body").append('<div><i class="c1" /><span>ok</span></div>');在舊版 jQuery 當(dāng)中,頁面內(nèi)容渲染得到:
<div><i class="c1"></i><span>ok</span></div>
但是在新版 jQuery 3.6.1 里得到的卻是:
<div><i class="c1"><span>hello</span></i></div>
兩者差別就是,針對 <i /> 的寫法,渲染有不同。
造成這個差異的原因是什么呢?我們拋開 jQuery ,試試原生 JS 的效果:
document.children[0].children[1].innerHTML = '<div><i class="c1" /><span>ok</span>';
結(jié)果渲染得到的與 jQuery 3.6.1 是一致的。也就是針對 <i /> 這種寫法,HTML 5 是不認(rèn)的,因為 <i> 本身不屬于 HTML5 非閉合標(biāo)簽 (所謂 非閉合標(biāo)簽,是類似 <meta> <br> 這種,數(shù)量有限),則 渲染引擎 將 <i /> 視為未閉合。實際上 <element /> 的寫法,屬于 XHTML ,而不是 HTML5 的規(guī)范。
奇怪的是,為啥舊版 jQuery 我們用著就沒有問題,難道它在 append 方法里做了什么特殊處理?
排查了源碼,果不其然。如下:
// Convert html string into DOM nodes
if ( typeof elem === "string" ) {
if ( !rhtml.test( elem ) ) {
elem = context.createTextNode( elem );
} else {
// Fix "XHTML"-style tags in all browsers
elem = elem.replace(rxhtmlTag, "<$1></$2>");注釋上明確說了 Fix "XHTML"-style tags in all browsers 。哎,我們這些一直誤用的人啊,被老版本 jQuery 保護的太好了!
OK,為了確保此前的UI代碼能繼續(xù)使用,我們還是要得來個解決方案:
var oldAppend = jQuery.fn.append;
jQuery.fn.append =function( ) {
/**
* 相關(guān)素材來自 jquery 1.7.2
*/
var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig;
if (arguments.length > 0
&& typeof(arguments[0]) == "string" ) {
var elem = arguments[0];
elem = elem.replace(rxhtmlTag, "<$1></$2>");
arguments[0] = elem;
}
return oldAppend.apply( this, arguments );
};至此,遇到的不兼容問題基本都解決了。我們將包含前述問題的解決辦法,匯總到 以下 js 代碼里,需要的各位可以自取。
( function() {
/**
* 注意,以下代碼,應(yīng)確保 引用在 jquery 3.6.1, jquery-migrate-3.4.0.min.js,以及 jquery-ui-1.8.10.custom.min.js 等內(nèi)容之后,否則
* 相關(guān)的 代碼托管 可能會被取代 而 無效。
*/
jQuery.curCSS = function(element, prop, val) {
return jQuery(element).css(prop, val);
};
/**
* James add on 2022.11.24 , 相關(guān)代碼摘錄自 jquery 1.7.2
* 此 修復(fù)是為了 兼容 以下有關(guān)寫法,在 append 到 jquery 對象里時,能適應(yīng) 老版本的渲染邏輯。
* $.append("<div><i class='abc' /> <span>ttt</span></div>");
* 上述內(nèi)容,在 jquery 1.7.2 版本里,會被渲染為:
* <div><i class='abc'></i><span>ttt</span></div>
*
* 而在 jquery 3.6.1 里,則會被渲染為:
* <div><i class='abc'><span>ttt</span></i></div>
*
* 這是由于 在 舊版 jquery 里,針對 非閉合的標(biāo)簽有過特定處理,而在 jquery 3.6.1 里則移除了這個做法。
* 因此直接在 element 的 innterHtml 里面寫入 <div><i class='abc' /> <span>ttt</span></div> 這個內(nèi)容,
* 與 3.6.1 里面是一致的。
*
* 所以根本上是不規(guī)范的 html 寫法,只是老版本 jquery 做了容錯,而新版本沒有容錯,因而導(dǎo)致問題。
*
*/
var oldAppend = jQuery.fn.append;
jQuery.fn.append =function( ) {
/**
* 相關(guān)素材來自 jquery 1.7.2
*/
var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig;
if (arguments.length > 0
&& typeof(arguments[0]) == "string" ) {
var elem = arguments[0];
elem = elem.replace(rxhtmlTag, "<$1></$2>");
arguments[0] = elem;
}
return oldAppend.apply( this, arguments );
};
var oldOuterWidth = jQuery.fn.outerWidth;
jQuery.fn.outerWidth =function( ) {
if (arguments.length <= 0) {
arguments[0] = false;
arguments.length = 1;
}
var result = oldOuterWidth.apply( this, arguments ) ;
return result === undefined ? 0 : result;
};
var oldOuterHeight = jQuery.fn.outerHeight;
jQuery.fn.outerHeight =function( ) {
if (arguments.length <= 0) {
arguments[0] = false;
arguments.length = 1;
}
var result = oldOuterHeight.apply( this, arguments );
return result === undefined ? 0 : result;
};
})();注意,上述代碼在頁面中的引入,應(yīng)確保在 jquery 3.6.1, jquery-migrate-3.4.0.min.js,以及 jquery-ui-1.8.10.custom.min.js 等內(nèi)容之后,否則可能會被取代而無效。
總結(jié)
到此這篇關(guān)于升級到j(luò)Query 3.6.1遇見的一些坑以及應(yīng)對辦法的文章就介紹到這了,更多相關(guān)升級jQuery 3.6.1的坑內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jQuery滾動監(jiān)聽實現(xiàn)商城樓梯式導(dǎo)航效果
這篇文章主要介紹了jQuery滾動監(jiān)聽,實現(xiàn)商城樓梯式導(dǎo)航,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-03-03

