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


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数据表格插件
Jul 17 Javascript
jquery.validate分组验证代码
Mar 17 Javascript
js 验证密码强弱的小例子
Mar 21 Javascript
纯js实现遮罩层效果原理分析
May 27 Javascript
Javascript常用小技巧汇总
Jun 24 Javascript
jQuery animate easing使用方法图文详解
Jun 17 Javascript
JS button按钮实现submit按钮提交效果
Nov 01 Javascript
js事件委托和事件代理案例分享
Jul 25 Javascript
Vue.js分页组件实现:diVuePagination的使用详解
Jan 10 Javascript
使用JS监听键盘按下事件(keydown event)
Nov 07 Javascript
Vue使用富文本编辑器Vue-Quill-Editor(含图片自定义上传服务、清除复制粘贴样式等)
May 15 Javascript
Openlayers+EasyUI Tree动态实现图层控制
Sep 28 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生成验证码时“图像因其本身有错无法显示”的解决方法
2013/08/07 PHP
定义select的边框颜色
2008/04/28 Javascript
JavaScript实现对下拉列表值进行排序的方法
2015/07/15 Javascript
JavaScript实现的经典文件树菜单效果
2015/09/08 Javascript
jQuery+CSS3+Html5实现弹出层效果实例代码(附源码下载)
2016/05/16 Javascript
AngularJS基础 ng-include 指令示例讲解
2016/08/01 Javascript
js数组实现权重概率分配
2017/09/12 Javascript
Angular4编程之表单响应功能示例
2017/12/13 Javascript
深入理解react 组件类型及使用场景
2019/03/07 Javascript
js实现固定区域内的不重叠随机圆
2019/10/24 Javascript
vue.js路由mode配置之去掉url上默认的#方法
2019/11/01 Javascript
Postman无法正常返回结果问题解决
2020/08/28 Javascript
js仿淘宝放大镜效果
2020/12/28 Javascript
[00:43]DOTA2小紫本全民票选福利PA至宝全方位展示
2014/11/25 DOTA
在服务器端实现无间断部署Python应用的教程
2015/04/16 Python
Python中的pack和unpack的使用
2018/03/12 Python
关于python中plt.hist参数的使用详解
2019/11/28 Python
Python netmiko模块的使用
2020/02/14 Python
Python sqlite3查询操作过程解析
2020/02/20 Python
如何通过python计算圆周率PI
2020/11/11 Python
一款纯css3制作的2015年元旦雪人动画特效教程
2014/12/29 HTML / CSS
CSS+jQuery实现的在线答题功能
2015/04/25 HTML / CSS
香港连卡佛百货官网:Lane Crawford
2019/09/04 全球购物
BSTN意大利:德国街头和运动文化高品质商店
2020/12/22 全球购物
学生发电厂实习自我鉴定
2013/09/22 职场文书
2014领导干部学习焦裕禄同志先进事迹思想汇报
2014/09/19 职场文书
交通事故一次性赔偿协议书范本
2014/11/02 职场文书
党员示范岗材料
2014/12/19 职场文书
会计专业求职信范文
2015/03/19 职场文书
谢师宴家长致辞
2015/07/27 职场文书
婚礼领导致辞大全
2015/07/28 职场文书
教师远程研修感悟
2015/11/18 职场文书
《富饶的西沙群岛》教学反思
2016/02/16 职场文书
python迷宫问题深度优先遍历实例
2021/06/20 Python
灵能百分百第三季什么时候来?
2022/03/15 日漫
Spring Boot配合PageHelper优化大表查询数据分页
2022/04/20 Java/Android