高效的获取当前元素是父元素的第几个子元素


Posted in Javascript onOctober 15, 2013

例如处理事件的时候,有时候需要知道当前点击的是第几个子节点,而HTML DOM本身并没有直接提供相应的属性,需要自己来计算。

从一个索引序号,很容易得到该索引对应的子节点或者子元素,直接用parentNode.childNodes[index] 或 parentNode.children[index] 就行。

但反过来,已知一个节点或元素对象,要知道它的索引序号则没有那么直接了。

一些特殊的元素,HTML DOM有对应的属性表示其索引序号,主要是表格的TD 和 TR 元素。

表格单元格TD元素有 cellIndex 属性。

表格行TR元素有rowIndex属性。

如果你的处理目标刚好就是表格,则优先使用这两个属性。

但一般的节点或元素并没有 childNodeIndex 或者 childElementIndex 之类的属性。

解决方案主要分为两类:

一、预先计算并缓存节点的索引号(可以存在节点属性或者js变量中)。

二、实时计算,需要遍历部分节点。

应用中,可根据不同的实际情况,选用上述两类方案之一。

适用方案一的情形:

当DOM结构不会变化,并且需要频繁的获取个别节点的索引,可采用方案一。

优点是后续读取快,缺点是初始化需要开销,DOM结构变化后需要重新初始化。

适用方案二的情形:

DOM结构可能会变化,并且不是特别频繁的获取个别节点的索引,可采用方案二。

优点是不受DOM结构变化的影响,不会污染DOM结构,没有初始化开销。缺点是不适合高频率调用。

一般而言,采用方案二是更好的,因为通常DOM树规模是比较有限的,一轮的循环并不会导致显著降低整体性能,而其优点则是显著的。

对于IE浏览器,则有更直接的方法。

从IE4到IE11,都有sourceIndex属性,这个属性表示了元素在DOM树的顺序,比较元素和父元素的sourceIndex的差值就很容易知道元素是第几个子元素了。

我写了一段函数来区分处理,在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; 
}

上面的函数只是计算元素Element,也就是nodeType为1的节点,文本节点、注释节点等将不被统计。如果需要计算所有节点在内,则不能适用sourceIndex,因为该属性只针对Element. previousElementSibling也要相应的改为previousSibling. 那就要写成如下的函数了:
function getNodeIndex(node){ 
var i=0; 
while(ele = ele.previousSibling){ 
i++; 
} 
return i; 
}

后记:在非IE下,有 compareDocumentPosition 方法用于比较节点的位置关系,但经过测试该方法的性能非常差,其内部的实现机制肯定不是像IE那样缓存了资源索引号的,如果这个方法极高效,那就可采用二分法进行计算,从而提高效率,但目前还不可能。

最后的总结:

对于表格TD和TR元素优先使用cellIndex和rowIndex属性。

对于IE优先使用sourceIndex属性。

其它情形使用previousElementSibling 或 previousSibling 进行遍历。

compareDocumentPosition 方法的性能非常差。

Javascript 相关文章推荐
JQuery表单验证插件EasyValidator用法分析
Nov 15 Javascript
使用jQuery+EasyUI实现CheckBoxTree的级联选中特效
Dec 06 Javascript
JavaScript设计模式开发中组合模式的使用教程
May 18 Javascript
JS基于递归实现倒计时效果的方法
Nov 26 Javascript
Vue实现virtual-dom的原理简析
Jul 10 Javascript
详解如何使用PM2将Node.js的集群变得更加容易
Nov 15 Javascript
详解Vue改变数组中对象的属性不重新渲染View的解决方案
Sep 21 Javascript
js canvas实现画图、滤镜效果
Nov 27 Javascript
vue基础之事件v-onclick="函数"用法示例
Mar 11 Javascript
微信小程序如何自定义table组件
Jun 29 Javascript
layui 图片上传+表单提交+ Spring MVC的实例
Sep 21 Javascript
前端vue+express实现文件的上传下载示例
Feb 18 Vue.js
JS 实现点击a标签的时候让其背景更换
Oct 15 #Javascript
JS操作Cookies的小例子
Oct 15 #Javascript
如何在父窗口中得知window.open()出的子窗口关闭事件
Oct 15 #Javascript
JavaScript中prototype为对象添加属性的误区介绍
Oct 15 #Javascript
JS格式化数字保留两位小数点示例代码
Oct 15 #Javascript
js计算字符串长度包含的中文是utf8格式
Oct 15 #Javascript
Javascript中查找不以XX字符结尾的单词示例代码
Oct 15 #Javascript
You might like
图象函数中的中文显示
2006/10/09 PHP
php中导出数据到excel时数字变为科学计数的解决方法
2013/02/03 PHP
PHP人民币金额数字转中文大写的函数代码
2013/02/27 PHP
浅谈PHP定义命令空间的几个注意点(推荐)
2016/10/29 PHP
js触发onchange事件的方法说明
2014/03/08 Javascript
使用JavaScript的AngularJS库编写hello world的方法
2015/06/23 Javascript
学习JavaScript设计模式之责任链模式
2016/01/18 Javascript
Javascript中的迭代、归并方法详解
2016/06/14 Javascript
关于 jQuery Easyui异步加载tree的问题解析
2016/12/06 Javascript
js学习总结之DOM2兼容处理顺序问题的解决方法
2017/07/27 Javascript
页面缩放兼容性处理方法(zoom,Firefox火狐浏览器)
2017/08/29 Javascript
JS简单实现查看文档创建日期、修改日期和文档大小的方法示例
2018/04/08 Javascript
jQuery 实现倒计时天,时,分,秒功能
2018/07/31 jQuery
electron制作仿制qq聊天界面的示例代码
2018/11/26 Javascript
vue路由教程之静态路由
2019/09/03 Javascript
layui实现下拉复选功能的例子(包括数据的回显与上传)
2019/09/24 Javascript
[46:25]DOTA2上海特级锦标赛主赛事日 - 4 败者组第五轮 MVP.Phx VS EG第二局
2016/03/05 DOTA
[01:15]PWL S2开团时刻第二期——他们杀 我就白给
2020/11/25 DOTA
[02:22]完美世界DOTA2联赛PWL S3 集锦第一期
2020/12/15 DOTA
Python中列表和元组的相关语句和方法讲解
2015/08/20 Python
Python模糊查询本地文件夹去除文件后缀的实例(7行代码)
2017/11/09 Python
python之文件读取一行一行的方法
2018/07/12 Python
python实现周期方波信号频谱图
2018/07/21 Python
python 使用plt画图,去除图片四周的白边方法
2019/07/09 Python
python实现FTP循环上传文件
2020/03/20 Python
python 在sql语句中使用%s,%d,%f说明
2020/06/06 Python
Pycharm配置lua编译环境过程图解
2020/11/28 Python
python 合并多个excel中同名的sheet
2021/01/22 Python
泰国汽车、火车和轮渡票预订网站:Bus Online Ticket
2017/09/09 全球购物
美国小蜜蜂Burt’s Bees德国官网:天然唇部、皮肤和身体护理产品
2020/06/14 全球购物
全国文明单位申报材料
2014/05/31 职场文书
员工评语范文
2014/12/31 职场文书
销售业务员岗位职责
2015/02/13 职场文书
开除员工通知
2015/04/22 职场文书
Vue h函数的使用详解
2022/02/18 Vue.js
Java 超详细讲解IO操作字节流与字符流
2022/03/25 Java/Android