高效的獲取當(dāng)前元素是父元素的第幾個(gè)子元素
更新時(shí)間:2013年10月15日 16:46:47 作者:
例如處理事件的時(shí)候,有時(shí)候需要知道當(dāng)前點(diǎn)擊的是第幾個(gè)子節(jié)點(diǎn),而HTML DOM本身并沒(méi)有直接提供相應(yīng)的屬性,需要自己來(lái)計(jì)算。感興趣的朋友可以了解下本文
例如處理事件的時(shí)候,有時(shí)候需要知道當(dāng)前點(diǎn)擊的是第幾個(gè)子節(jié)點(diǎn),而HTML DOM本身并沒(méi)有直接提供相應(yīng)的屬性,需要自己來(lái)計(jì)算。
從一個(gè)索引序號(hào),很容易得到該索引對(duì)應(yīng)的子節(jié)點(diǎn)或者子元素,直接用parentNode.childNodes[index] 或 parentNode.children[index] 就行。
但反過(guò)來(lái),已知一個(gè)節(jié)點(diǎn)或元素對(duì)象,要知道它的索引序號(hào)則沒(méi)有那么直接了。
一些特殊的元素,HTML DOM有對(duì)應(yīng)的屬性表示其索引序號(hào),主要是表格的TD 和 TR 元素。
表格單元格TD元素有 cellIndex 屬性。
表格行TR元素有rowIndex屬性。
如果你的處理目標(biāo)剛好就是表格,則優(yōu)先使用這兩個(gè)屬性。
但一般的節(jié)點(diǎn)或元素并沒(méi)有 childNodeIndex 或者 childElementIndex 之類的屬性。
解決方案主要分為兩類:
一、預(yù)先計(jì)算并緩存節(jié)點(diǎn)的索引號(hào)(可以存在節(jié)點(diǎn)屬性或者js變量中)。
二、實(shí)時(shí)計(jì)算,需要遍歷部分節(jié)點(diǎn)。
應(yīng)用中,可根據(jù)不同的實(shí)際情況,選用上述兩類方案之一。
適用方案一的情形:
當(dāng)DOM結(jié)構(gòu)不會(huì)變化,并且需要頻繁的獲取個(gè)別節(jié)點(diǎn)的索引,可采用方案一。
優(yōu)點(diǎn)是后續(xù)讀取快,缺點(diǎn)是初始化需要開(kāi)銷,DOM結(jié)構(gòu)變化后需要重新初始化。
適用方案二的情形:
DOM結(jié)構(gòu)可能會(huì)變化,并且不是特別頻繁的獲取個(gè)別節(jié)點(diǎn)的索引,可采用方案二。
優(yōu)點(diǎn)是不受DOM結(jié)構(gòu)變化的影響,不會(huì)污染DOM結(jié)構(gòu),沒(méi)有初始化開(kāi)銷。缺點(diǎn)是不適合高頻率調(diào)用。
一般而言,采用方案二是更好的,因?yàn)橥ǔOM樹(shù)規(guī)模是比較有限的,一輪的循環(huán)并不會(huì)導(dǎo)致顯著降低整體性能,而其優(yōu)點(diǎn)則是顯著的。
對(duì)于IE瀏覽器,則有更直接的方法。
從IE4到IE11,都有sourceIndex屬性,這個(gè)屬性表示了元素在DOM樹(shù)的順序,比較元素和父元素的sourceIndex的差值就很容易知道元素是第幾個(gè)子元素了。
我寫(xiě)了一段函數(shù)來(lái)區(qū)分處理,在IE下采用sourceIndex高效判斷,非IE則采用一般遍歷。
function getChildrenIndex(ele){
//IE is simplest and fastest
if(ele.sourceIndex){
return ele.sourceIndex - ele.parentNode.sourceIndex - 1;
}
//other browsers
var i=0;
while(ele = ele.previousElementSibling){
i++;
}
return i;
}
上面的函數(shù)只是計(jì)算元素Element,也就是nodeType為1的節(jié)點(diǎn),文本節(jié)點(diǎn)、注釋節(jié)點(diǎn)等將不被統(tǒng)計(jì)。如果需要計(jì)算所有節(jié)點(diǎn)在內(nèi),則不能適用sourceIndex,因?yàn)樵搶傩灾会槍?duì)Element. previousElementSibling也要相應(yīng)的改為previousSibling. 那就要寫(xiě)成如下的函數(shù)了:
function getNodeIndex(node){
var i=0;
while(ele = ele.previousSibling){
i++;
}
return i;
}
后記:在非IE下,有 compareDocumentPosition 方法用于比較節(jié)點(diǎn)的位置關(guān)系,但經(jīng)過(guò)測(cè)試該方法的性能非常差,其內(nèi)部的實(shí)現(xiàn)機(jī)制肯定不是像IE那樣緩存了資源索引號(hào)的,如果這個(gè)方法極高效,那就可采用二分法進(jìn)行計(jì)算,從而提高效率,但目前還不可能。
最后的總結(jié):
對(duì)于表格TD和TR元素優(yōu)先使用cellIndex和rowIndex屬性。
對(duì)于IE優(yōu)先使用sourceIndex屬性。
其它情形使用previousElementSibling 或 previousSibling 進(jìn)行遍歷。
compareDocumentPosition 方法的性能非常差。
從一個(gè)索引序號(hào),很容易得到該索引對(duì)應(yīng)的子節(jié)點(diǎn)或者子元素,直接用parentNode.childNodes[index] 或 parentNode.children[index] 就行。
但反過(guò)來(lái),已知一個(gè)節(jié)點(diǎn)或元素對(duì)象,要知道它的索引序號(hào)則沒(méi)有那么直接了。
一些特殊的元素,HTML DOM有對(duì)應(yīng)的屬性表示其索引序號(hào),主要是表格的TD 和 TR 元素。
表格單元格TD元素有 cellIndex 屬性。
表格行TR元素有rowIndex屬性。
如果你的處理目標(biāo)剛好就是表格,則優(yōu)先使用這兩個(gè)屬性。
但一般的節(jié)點(diǎn)或元素并沒(méi)有 childNodeIndex 或者 childElementIndex 之類的屬性。
解決方案主要分為兩類:
一、預(yù)先計(jì)算并緩存節(jié)點(diǎn)的索引號(hào)(可以存在節(jié)點(diǎn)屬性或者js變量中)。
二、實(shí)時(shí)計(jì)算,需要遍歷部分節(jié)點(diǎn)。
應(yīng)用中,可根據(jù)不同的實(shí)際情況,選用上述兩類方案之一。
適用方案一的情形:
當(dāng)DOM結(jié)構(gòu)不會(huì)變化,并且需要頻繁的獲取個(gè)別節(jié)點(diǎn)的索引,可采用方案一。
優(yōu)點(diǎn)是后續(xù)讀取快,缺點(diǎn)是初始化需要開(kāi)銷,DOM結(jié)構(gòu)變化后需要重新初始化。
適用方案二的情形:
DOM結(jié)構(gòu)可能會(huì)變化,并且不是特別頻繁的獲取個(gè)別節(jié)點(diǎn)的索引,可采用方案二。
優(yōu)點(diǎn)是不受DOM結(jié)構(gòu)變化的影響,不會(huì)污染DOM結(jié)構(gòu),沒(méi)有初始化開(kāi)銷。缺點(diǎn)是不適合高頻率調(diào)用。
一般而言,采用方案二是更好的,因?yàn)橥ǔOM樹(shù)規(guī)模是比較有限的,一輪的循環(huán)并不會(huì)導(dǎo)致顯著降低整體性能,而其優(yōu)點(diǎn)則是顯著的。
對(duì)于IE瀏覽器,則有更直接的方法。
從IE4到IE11,都有sourceIndex屬性,這個(gè)屬性表示了元素在DOM樹(shù)的順序,比較元素和父元素的sourceIndex的差值就很容易知道元素是第幾個(gè)子元素了。
我寫(xiě)了一段函數(shù)來(lái)區(qū)分處理,在IE下采用sourceIndex高效判斷,非IE則采用一般遍歷。
復(fù)制代碼 代碼如下:
function getChildrenIndex(ele){
//IE is simplest and fastest
if(ele.sourceIndex){
return ele.sourceIndex - ele.parentNode.sourceIndex - 1;
}
//other browsers
var i=0;
while(ele = ele.previousElementSibling){
i++;
}
return i;
}
上面的函數(shù)只是計(jì)算元素Element,也就是nodeType為1的節(jié)點(diǎn),文本節(jié)點(diǎn)、注釋節(jié)點(diǎn)等將不被統(tǒng)計(jì)。如果需要計(jì)算所有節(jié)點(diǎn)在內(nèi),則不能適用sourceIndex,因?yàn)樵搶傩灾会槍?duì)Element. previousElementSibling也要相應(yīng)的改為previousSibling. 那就要寫(xiě)成如下的函數(shù)了:
復(fù)制代碼 代碼如下:
function getNodeIndex(node){
var i=0;
while(ele = ele.previousSibling){
i++;
}
return i;
}
后記:在非IE下,有 compareDocumentPosition 方法用于比較節(jié)點(diǎn)的位置關(guān)系,但經(jīng)過(guò)測(cè)試該方法的性能非常差,其內(nèi)部的實(shí)現(xiàn)機(jī)制肯定不是像IE那樣緩存了資源索引號(hào)的,如果這個(gè)方法極高效,那就可采用二分法進(jìn)行計(jì)算,從而提高效率,但目前還不可能。
最后的總結(jié):
對(duì)于表格TD和TR元素優(yōu)先使用cellIndex和rowIndex屬性。
對(duì)于IE優(yōu)先使用sourceIndex屬性。
其它情形使用previousElementSibling 或 previousSibling 進(jìn)行遍歷。
compareDocumentPosition 方法的性能非常差。
相關(guān)文章
微信小程序配置視圖層數(shù)據(jù)綁定相關(guān)示例
這篇文章主要為大家介紹了微信小程序配置視圖層數(shù)據(jù)綁定相關(guān)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪<BR>2022-04-04javascript獲取隱藏元素(display:none)的高度和寬度的方法
這篇文章主要介紹了javascript獲取隱藏元素(display:none)的高度和寬度的方法,實(shí)現(xiàn)方法比較復(fù)雜,需要的朋友可以參考下2014-06-06探究Javascript模板引擎mustache.js使用方法
這篇文章主要為大家介紹了Javascript模板引擎mustache.js使用方法,mustache.js是一個(gè)簡(jiǎn)單強(qiáng)大的Javascript模板引擎,使用它可以簡(jiǎn)化在js代碼中的html編寫(xiě),壓縮后只有9KB,非常值得在項(xiàng)目中使用,感興趣的小伙伴們可以參考一下2016-01-01純js實(shí)現(xiàn)倒計(jì)時(shí)功能
本文主要介紹了通過(guò)js實(shí)現(xiàn)頁(yè)面的倒計(jì)時(shí)功能的思路與方法,具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-01-01基于JavaScript實(shí)現(xiàn)右鍵菜單和拖拽功能
本文給大家分享基于js實(shí)現(xiàn)的右鍵菜單功能和拖拽功能的代碼解析,非常不錯(cuò),具有一定的參考借鑒價(jià)值,感興趣的朋友一起看看吧2016-11-11微信小程序?qū)崿F(xiàn)九宮格翻牌動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)九宮格翻牌動(dòng)畫(huà),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04基于JavaScript實(shí)現(xiàn)年份數(shù)字拼圖效果
時(shí)光荏苒,2022年又要收尾了,公司的年會(huì)是不是都安排上了?前幾天看到一個(gè)年會(huì)抽獎(jiǎng)系統(tǒng),功能十分的強(qiáng)大,其中有一個(gè)年份數(shù)字的拼圖效果深深的吸引了哥,決定用JS實(shí)現(xiàn)一下該效果,需要的可以參考一下2022-12-12一個(gè)用javascript寫(xiě)的select支持上下鍵、首字母篩選以及回車取值的功能
一個(gè)用javascript寫(xiě)的select支持上下鍵、首字母篩選以及回車取值的功能2009-09-09