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


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.uploadify 上传文件插件的使用详解 for ASP.NET
Jan 22 Javascript
cnblogs中在闪存中屏蔽某人的实现代码
Nov 14 Javascript
JS文本框不能输入空格验证方法
Mar 19 Javascript
jQuery背景插件backstretch使用指南
Apr 21 Javascript
JavaScript常用判断写法大全(推荐)
May 30 Javascript
Web性能优化系列 10个提升JavaScript性能的技巧
Sep 27 Javascript
JavaScript中undefined和null的区别
May 03 Javascript
cropper js基于vue的图片裁剪上传功能的实现代码
Mar 01 Javascript
解决vue项目使用font-awesome,build后路径的问题
Sep 01 Javascript
微信小程序以ssm做后台开发的实现示例
Apr 08 Javascript
JavaScript中变量提升和函数提升的详解
Aug 07 Javascript
vue实现div可拖动位置也可改变盒子大小的原理
Sep 16 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
PHP 5.3 下载时 VC9、VC6、Thread Safe、Non Thread Safe的区别分析
2011/03/28 PHP
PHP实现检测客户端是否使用代理服务器及其匿名级别
2015/01/07 PHP
PHP中预定义的6种接口介绍
2015/05/12 PHP
laravel 5.3 单用户登录简单实现方法
2019/10/14 PHP
jQuery 解析xml文件
2009/08/09 Javascript
jQuery判断元素上是否绑定了指定事件的方法
2015/03/17 Javascript
jquery实现的横向二级导航效果代码
2015/08/26 Javascript
js clearInterval()方法的定义和用法
2015/11/11 Javascript
javascript中去除数组重复元素的实现方法【实例】
2016/04/12 Javascript
Javascript日期格式化format函数的使用方法
2016/08/30 Javascript
javaScript基础详解
2017/01/19 Javascript
微信小程序 列表的上拉加载和下拉刷新的实现
2017/04/01 Javascript
使用Vue制作图片轮播组件思路详解
2018/03/21 Javascript
echarts同一页面中四个图表切换的js数据交互方法示例
2018/07/03 Javascript
jquery 动态遍历select 赋值的实例
2018/09/12 jQuery
微信小程序 调用微信授权窗口相关问题解决
2019/07/25 Javascript
vue使用codemirror的两种用法
2019/08/27 Javascript
快速解决layui弹窗按enter键不停弹窗的问题
2019/09/18 Javascript
layui输入框中只允许输入整数的实现方法
2019/09/18 Javascript
微信小程序自定义菜单切换栏tabbar组件代码实例
2019/12/30 Javascript
关于vue的列表图片选中打钩操作
2020/09/09 Javascript
vue实现登录功能
2020/12/31 Vue.js
[01:12:08]LGD vs OG 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.24
2019/09/10 DOTA
PyQt5 界面显示无响应的实现
2020/03/26 Python
台湾最大网路书店:博客来
2018/03/18 全球购物
人力管理专业毕业生求职信
2014/02/27 职场文书
国家励志奖学金个人先进事迹材料
2014/05/04 职场文书
爱护公共设施的标语
2014/06/24 职场文书
好媳妇事迹材料
2014/12/24 职场文书
2015年老干部工作总结
2015/04/23 职场文书
安全承诺书格式范本
2015/04/28 职场文书
《夸父追日》教学反思
2016/02/20 职场文书
职业规划从高考志愿专业选择开始
2019/08/08 职场文书
Java面试题冲刺第十五天--设计模式
2021/08/07 面试题
前端vue+express实现文件的上传下载示例
2022/02/18 Vue.js
MySQL创建管理KEY分区
2022/04/13 MySQL