JavaScript通過HTML的class來獲取HTML元素的方法總結(jié)
對于js來說,我想每一個(gè)剛接觸它的人都應(yīng)該會抱怨:為什么沒有一個(gè)通過class來獲取元素的方法。盡管現(xiàn)在高版本的瀏覽器已經(jīng)支持getElementsByClassName()函數(shù),但是對于低版本瀏覽器來說,還是無法兼容,在脫離其他庫的時(shí)候,還是得自己封裝一個(gè)方法。
方法一
function getByClass1(parent, cls){
var res = []; //存放匹配結(jié)果的數(shù)組
var ele = parent.getElementsByTagName('*');
for(var i = 0; i < ele.length; i++){
if(ele[i].className == cls){
res.push(ele[i]);
}
}
return res;
}
當(dāng)然class里的值只有一個(gè)時(shí),上面的方法沒問題,但當(dāng)值為多個(gè)時(shí),就會出現(xiàn)問題。
<div class="test"></div> <div class="test box"></div> <script> getByClass1(document, 'test'); //只獲取到第一個(gè)div </script>
方法二
出現(xiàn)問題的時(shí)候,我們會嘗試著改進(jìn),對于多類名的情況我們可以用正則去匹配是否包含所要查找的class名,于是就出現(xiàn)了下面這種寫法:
function getByClass2(parent, cls){
var res = [];
var reg = new RegExp('\\b' + cls + '\\b', 'i'); //匹配cls是一個(gè)獨(dú)立的單詞
var ele = parent.getElementsByTagName('*');
for(var i = 0; i < ele.length; i++){
if(reg.test(ele[i].className)){
res.push(ele[i]);
}
}
return res;
}
這種方法看似可以,解決了getByClass1()的問題,我也用了好長一段時(shí)間,但是還會有一個(gè)隱藏的bug??聪旅娴睦樱?/p>
<div class="test"></div> <div class="test_box"></div> <div class="test-box"></div> <script> getByClass2(document, 'test'); //結(jié)果獲取到了第一個(gè)div和第三個(gè)div </script>
理論上應(yīng)該只獲取到第一個(gè),但是卻和我們預(yù)期不一樣。這個(gè)bug源于下面這段代碼里的\b
var reg = new RegExp('\\b' + cls + '\\b', 'i');
我們先來看下\b在正則中的表示的意思
\b是正則表達(dá)式規(guī)定的一個(gè)特殊代碼,代表著單詞的開頭或結(jié)尾,也就是單詞的分界處。
通俗點(diǎn)說:\b就是匹配一個(gè)單詞(從左邊界到右邊界)。
而問題也就出在這里,\b把除字母、數(shù)字、下劃線外的其他字符都當(dāng)成是邊界,對于上面的例子中第三個(gè)class值為test-box,\b匹配時(shí),把連字符(-)當(dāng)作單詞邊界,所以也匹配了第三個(gè)div。
方法三
因此我們還需要對上面方法進(jìn)行進(jìn)一步改進(jìn),這里參考了stackoverflow上提到的一種方法:
How to Get Element By Class in JavaScript?
改進(jìn)后的代碼如下:
function getByClass3(parent, cls){
var res = [];
var reg = new RegExp(' ' + cls + ' ', 'i'); //匹配cls時(shí),兩邊需要有空格
var ele = parent.getElementsByTagName('*');
for(var i = 0; i < ele.length; i++){
if(reg.test(' ' + ele[i].className + ' ')){
res.push(ele[i]);
}
}
return res;
}
這種方法舍去了用\b而采用空格來匹配邊界,先在獲取到的className值兩邊加上空格,這樣就保證了className里的每個(gè)值兩邊都會有空格,然后再用正則去匹配。
用這種方法暫時(shí)還未發(fā)現(xiàn)問題,但是使用時(shí),方法中的單引號內(nèi)的空格一定不能落下。
方法四
function getByClass3(parent, cls){
var res = [];
var reg = new RegExp('(^|\\s)' + cls + '($|\\s)', 'i');
var ele = parent.getElementsByTagName('*');
for(var i = 0; i < ele.length; i++){
if(reg.test(ele[i].className)){
res.push(ele[i]);
}
}
return res;
}
空格完全用正則來處理,這樣省去了空格容易落下的問題,代碼也更美觀精簡。
那么這種方法是否就是比較完美的呢,其實(shí)不然,下面來看下更優(yōu)的方案。
方法五(完美版)
文章開頭已經(jīng)提到,高版本的瀏覽器已經(jīng)支持getElementsByClassName()方法。出于性能考慮,對支持的瀏覽器使用原生方法勢必會更好。而對于低版本的瀏覽器使用上面的方法四。
function getByClass(parent, cls){
if(parent.getElementsByClassName){
return parent.getElementsByClassName(cls);
}else{
var res = [];
var reg = new RegExp(' ' + cls + ' ', 'i')
var ele = parent.getElementsByTagName('*');
for(var i = 0; i < ele.length; i++){
if(reg.test(' ' + ele[i].className + ' ')){
res.push(ele[i]);
}
}
return res;
}
}
當(dāng)然方法五自認(rèn)為是相對較好的方案,如果有更優(yōu)秀的方法歡迎留言補(bǔ)充。
相關(guān)文章
Django1.7+JQuery+Ajax驗(yàn)證用戶注冊集成小例子
下面是散仙使用Django+Jquery+Ajax的方式來模擬實(shí)現(xiàn)了一個(gè)驗(yàn)證用戶注冊時(shí),用戶名存在不存在的一個(gè)小應(yīng)用。注意,驗(yàn)證存在不存在使用的是Ajax的方式,不用讓用戶點(diǎn)擊按鈕驗(yàn)證是否存在,需要的朋友可以參考下2017-04-04
JavaScript彈出新窗口后向父窗口輸出內(nèi)容的方法
這篇文章主要介紹了JavaScript彈出新窗口后向父窗口輸出內(nèi)容的方法,涉及javascript窗口操作的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04
JavaScript設(shè)計(jì)模式學(xué)習(xí)之適配器模式
這篇文章主要介紹了JavaScript設(shè)計(jì)模式之適配器模式,對設(shè)計(jì)模式不熟悉的同學(xué),可以參考學(xué)習(xí)一下2021-04-04
Bootstrap Metronic完全響應(yīng)式管理模板學(xué)習(xí)筆記
這篇文章主要為大家分享了Bootstrap Metronic完全響應(yīng)式管理模板學(xué)習(xí)筆記,感興趣的小伙伴們可以參考一下2016-07-07
JavaScript基于libgif.js實(shí)現(xiàn)控制gif動畫幀
這篇文章主要為大家詳細(xì)介紹了JavaScript如何利用libgif.js插件控制gif動畫幀,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02
js內(nèi)置對象處理_打印學(xué)生成績單的簡單實(shí)現(xiàn)
下面小編就為大家?guī)硪黄猨s內(nèi)置對象處理_打印學(xué)生成績單的簡單實(shí)現(xiàn)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09
JS實(shí)現(xiàn)將圖片轉(zhuǎn)為base64格式
Base64是一種用64個(gè)字符來表示任意二進(jìn)制數(shù)據(jù)的方法,這篇文章主要為大家介紹了如何實(shí)現(xiàn)將圖片轉(zhuǎn)為base64格式,感興趣的小伙伴可以學(xué)習(xí)一下2023-07-07

