JavaScript跨瀏覽器獲取頁面中相同class節(jié)點(diǎn)的方法
來源:易賢網(wǎng) 閱讀:851 次 日期:2015-03-06 10:32:00
溫馨提示:易賢網(wǎng)小編為您整理了“JavaScript跨瀏覽器獲取頁面中相同class節(jié)點(diǎn)的方法”,方便廣大網(wǎng)友查閱!

這篇文章主要介紹了JavaScript跨瀏覽器獲取頁面中相同class節(jié)點(diǎn)的方法,本文講解使用getELementsByClassName函數(shù)解決這個需求,并給了一個開源的getELementsByClassName函數(shù)實現(xiàn),功能更加強(qiáng)大,需要的朋友可以參考下

網(wǎng)頁開發(fā)時,在很多時候我們需要操作相同類名的元素,即class相同的元素。昨天參加筆試,有一道相關(guān)的題目沒答上來:

JavaScript獲取頁面中class為test的節(jié)點(diǎn)

于是收集了一些相關(guān)的資料,在本文中列舉了兩種我覺得比較好的方法,不足之處,還望大家批評指正。如果大家有更好的方法,希望可以分享。

Solution1 Jeremy Keuth方案

Jeremy Keuth大叔在《JavaScript DOM 編程藝術(shù)》(第2版)(英文:DOM Scripting-Web Design with JavaScript and the Document Object Model)一書的第三章第四節(jié)中講到了getElementsByClass這個方法,并講到了如何在不支持該屬性的瀏覽器(IE6,IE7和IE8,讓我們鄙視他們)中應(yīng)用這一方法,摘錄在此,個別地方有修改。

HTML5 DOM中新增了一個方法讓我們通過class屬性中的類名來訪問元素,這就是:getELementsByClassName,由于方法比較新,某些的DOM實現(xiàn)里還沒有,因此在使用的時候要當(dāng)心。下面我們先來看一看這個方法能幫我們做什么,然后在討論怎么可靠的使用該方法。

與getELementsByTagName方法類似,getElementsByClassName也只接受一個參數(shù),就是類名:

代碼如下:

getElementsByClassName(class)

這個方法的返回值也與getElementsByTagName類似,都是一個具有相同類名的元素的數(shù)組,下面這行代碼返回的就是一個數(shù)組,其中包含類名為“sale”的所有元素:

代碼如下:

document.getElementsByClassName("sale")

使用這個方法還可以查找那些帶有多個類名的元素。要指定多個類名,只要在字符串參數(shù)中用空格分隔類名即可。例如,在<script>標(biāo)簽中添加下面這行代碼:

代碼如下:

alert(document.getElementsByClassName("sale important").length);

完整代碼

代碼如下:

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>Shopping List</title>

</head>

<body>

<h1>What to buy</h1>

<p title="a gentle reminder">Don't forget to buy this stuff.</p>

<ul id="purchase">

<li>A thin of beans</li>

<li class="sale">Cheese</li>

<li class="sale important">Milk</li>

</ul>

<script>

alert(document.getElementsByClassName("sale important").length);

</script>

</body>

</html>

你會看到警告框中顯示1,表示只有一個元素匹配,因為只有一個元素同時帶有”important”和”sale”類名。注意,即使在元素的class屬性中,類名的順序是”sale important”而非參數(shù)中指定的”important sale”,也會照樣匹配該元素。不僅類名的實際順序不重要,就算元素還帶有更多類名也沒有關(guān)系。與使用getELementsByTagName一樣,也可以組合使用getElementsByClassName和getElementById。如果你想知道在id為purchase的元素中有多少類名包含test的列表項,可以先找到那個特定的對象,然后再調(diào)用getElementsByClassName:

代碼如下:

var shopping=document.getElementById("purchase");

var sales = shopping.getElementsByClassName("sale");

這樣,sales數(shù)組中包含的就只是位于”purchase”列表中的帶有”sales”類的元素,運(yùn)行下面這行代碼,就會看到sales數(shù)組包含兩項:

代碼如下:

alert(sales.length);

這個getELementsByClassName方法非常有用,但只有較新的瀏覽器(Safari 3.1,Chorme,F(xiàn)irefox 3 and Opera 9.5以上)才支持它。為了彌補(bǔ)這一不足,DOM腳本程序員需要使用已有的DOM方法來實現(xiàn)自己的getElementsByClassName,有點(diǎn)像成人禮似的。而多數(shù)情況下,他們的實現(xiàn)過程都與下面這個getElementsByClassName大致相似,這個函數(shù)能適用于新老瀏覽器。

代碼如下:

function getElementsByClassName(node,classname){

if(node.getElementsByClassName){

return node.getElementsByClassName(classname);

}else{

var results = [];

var elems = node.getElementsByTagName("*");

for(var i=0;i<elems.length;i++){

if(elems[i].className.indexOf(classname)!=-1){

results[results.length]=elems[i];

}

}

return results;

}

}

這個getElementsByClassName函數(shù)接受兩個參數(shù)。第一個node表示DOM樹中的搜索起點(diǎn),第二個classname就是要搜索的類名了。如果傳入節(jié)點(diǎn)上已經(jīng)存在了適當(dāng)?shù)膅etElementsByClassName函數(shù),那么這個新函數(shù)就直接返回相應(yīng)的節(jié)點(diǎn)列表。如果getElementsByClassName函數(shù)不存在,這個新函數(shù)就會循環(huán)遍歷所有標(biāo)簽,查找?guī)в邢鄳?yīng)類名的元素。

這個方法的缺點(diǎn)是不適用于多個類名。

如果使用這個函數(shù)來模擬前面取得購物列表的操作,就可以這樣寫:

代碼如下:

var shopping=document.getElementById("purchase");

var sales = shopping.getElementsByClassName(shopping,"test");

console.log(sales);

因此,要解決文章開頭的那道題目,所用代碼如下:

代碼如下:

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<title>Shopping List</title>

</head>

<body>

<h1>What to buy</h1>

<p title="a gentle reminder">Don't forget to buy this stuff.</p>

<ul id="purchase">

<li>A thin of beans</li>

<li class="sale">Cheese</li>

<li class="sale important">Milk</li>

</ul>

<script>

function getElementsByClassName(node,classname){

if(node.getElementsByClassName){

return node.getElementsByClassName(classname);

}else{

var results = [];

var elems = node.getElementsByTagName("*");

for(var i=0;i<elems.length;i++){

if(elems[i].className.indexOf(classname)!=-1){

results[results.length]=elems[i];

}

}

return results;

}

}

var body = document.getElementsByTagName("body")[0];

var sales= getElementsByClassName(body,"sales");

console.log(sales);

</script>

</body>

</html>

Solution2 Robert Nyman方案

搜索匹配的DOM元素的方法還有很多,但真正高效的卻不多,Jeremy Keuth大叔的方法有一個缺點(diǎn)就是不能用于多個類名,2008年,Robert Nyman在文章 The Ultimate GetElementsByClassName, Anno 2008中提供了自己的解決方案。在2005年,Robert大叔就已經(jīng)給出了自己的getElementsByClassName的函數(shù),在2008年的時候,修改了部分代碼,添加了許多新的功能:

1.如果當(dāng)前瀏覽器支持getElementsByClassName函數(shù),則調(diào)用該原生函數(shù);

2.如果當(dāng)前瀏覽器支持則使用XPath;//小飛魚:一種瀏覽器內(nèi)置的定位XML文檔的強(qiáng)大方式,不過瀏覽器支持方面不統(tǒng)一

3.支持多個類名的搜索,不計先后順序;

4.返回真正的節(jié)點(diǎn)數(shù)組,而不是原生的一個nodelist。//小飛魚:原生的getElementsByClassName方法返回的是一個NodeList對象,它很像數(shù)組,有l(wèi)ength和數(shù)字索引屬性,但并不是數(shù)組,不能用pop,push等數(shù)組特有的方法,Robert提供的代碼中,將NodeList對象轉(zhuǎn)成了數(shù)組。可以將NodeList對象轉(zhuǎn)換成數(shù)組的方法:

代碼如下:

myList = Array.prototype.slice.call (myNodeList)

這是Robert大叔的方法,有些地方還不太明白,待我研究一下再來更新好了。

代碼如下:

/*

Developed by Robert Nyman,

Code/licensing:

*/

var getElementsByClassName = function (className, tag, elm){

if (document.getElementsByClassName) {

getElementsByClassName = function (className, tag, elm) {

elm = elm || document;

var elements = elm.getElementsByClassName(className),

nodeName = (tag)? new RegExp("" + tag + "", "i") : null,

returnElements = [],

current;

for(var i=0, il=elements.length; i<il; i+=1){

current = elements[i];

if(!nodeName || nodeName.test(current.nodeName)) {

returnElements.push(current);

}

}

return returnElements;

};

}

else if (document.evaluate) {

getElementsByClassName = function (className, tag, elm) {

tag = tag || "*";

elm = elm || document;

var classes = className.split(" "),

classesToCheck = "",

xhtmlNamespace = "",

namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,

returnElements = [],

elements,

node;

for(var j=0, jl=classes.length; j<jl; j+=1){

classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";

}

try {

elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);

}

catch (e) {

elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);

}

while ((node = elements.iterateNext())) {

returnElements.push(node);

}

return returnElements;

};

}

else {

getElementsByClassName = function (className, tag, elm) {

tag = tag || "*";

elm = elm || document;

var classes = className.split(" "),

classesToCheck = [],

elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),

current,

returnElements = [],

match;

for(var k=0, kl=classes.length; k<kl; k+=1){

classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "()"));

}

for(var l=0, ll=elements.length; l<ll; l+=1){

current = elements[l];

match = false;

for(var m=0, ml=classesToCheck.length; m<ml; m+=1){

match = classesToCheck[m].test(current.className);

if (!match) {

break;

}

}

if (match) {

returnElements.push(current);

}

}

return returnElements;

};

}

return getElementsByClassName(className, tag, elm);

};

更多信息請查看IT技術(shù)專欄

更多信息請查看腳本欄目
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報名

  • 報班類型
  • 姓名
  • 手機(jī)號
  • 驗證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報警專用圖標(biāo)