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


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 相关文章推荐
070823更新的一个[消息提示框]组件 兼容ie7
Aug 29 Javascript
深入认识javascript中的eval函数
Nov 02 Javascript
基于jquery的获取mouse坐标插件的实现代码
Apr 01 Javascript
js实现瀑布流的一种简单方法实例分享
Nov 04 Javascript
js变量、作用域及内存详解
Sep 23 Javascript
JS组件Bootstrap Table使用方法详解
Feb 02 Javascript
jQuery点击输入框显示验证码图片
May 19 Javascript
js修改onclick动作的四种方法(推荐)
Aug 18 Javascript
jQuery 的 ready()的纯js替代方法
Nov 20 Javascript
jQuery实现拖动剪裁图片作为头像
Dec 28 Javascript
JS将时间秒转换成天小时分钟秒的字符串
Jul 10 Javascript
如何使JavaScript休眠或等待
Apr 27 Javascript
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
德劲1107的电路分析与打磨
2021/03/02 无线电
PHP面向对象概念
2011/11/06 PHP
实用的PHP带公钥加密类分享(每次加密结果都不一样哦)
2014/08/20 PHP
ThinkPHP验证码和分页实例教程
2014/08/22 PHP
php实现xml与json之间的相互转换功能实例
2016/07/07 PHP
Yii2实现UploadedFile上传文件示例
2017/02/15 PHP
TP5框架实现一次选择多张图片并预览的方法示例
2020/04/04 PHP
JavaScript RegExp方法获取地址栏参数(面向对象)
2009/03/10 Javascript
让你的网站可编辑的实现js代码
2009/10/19 Javascript
Javascript base64编码实现代码
2011/12/02 Javascript
javascript中的括号()用法小结
2014/04/14 Javascript
jQuery实现提示密码强度的代码
2015/07/15 Javascript
Vue.js每天必学之指令系统与自定义指令
2016/09/07 Javascript
Javascript获取图片原始宽度和高度的方法详解
2016/09/20 Javascript
详解Vue2.0之去掉组件click事件的native修饰
2017/04/20 Javascript
Node.js上传文件功能之服务端如何获取文件上传进度
2018/02/05 Javascript
vue-rx的初步使用教程
2018/09/21 Javascript
jquery轻量级数字动画插件countUp.js使用详解
2019/10/17 jQuery
[02:53]DOTA2英雄基础教程 山岭巨人小小
2013/12/09 DOTA
[02:40]2014DOTA2 国际邀请赛中国区预选赛 四大豪门抵达华西村
2014/05/23 DOTA
[01:06:42]VP vs NewBee Supermajor 胜者组 BO3 第二场 6.5
2018/06/06 DOTA
python机器学习之神经网络(一)
2017/12/20 Python
Python实现的括号匹配判断功能示例
2018/08/25 Python
如何在 Django 模板中输出 "{{"
2020/01/24 Python
Python loguru日志库之高效输出控制台日志和日志记录
2020/03/07 Python
基于pycharm实现批量修改变量名
2020/06/02 Python
Python+kivy BoxLayout布局示例代码详解
2020/12/28 Python
日本食品网上商店:JaponShop.com
2017/11/28 全球购物
Expedia法国:全球最大在线旅游公司
2018/09/30 全球购物
New Balance澳大利亚官网:运动鞋和健身服装
2019/02/23 全球购物
大学生个人自荐信样本
2014/03/02 职场文书
项目施工员岗位职责
2014/03/09 职场文书
初三学生评语大全
2014/04/24 职场文书
环保建议书200字
2014/05/14 职场文书
小学开学标语
2014/07/01 职场文书
部队个人年终总结
2015/03/02 职场文书