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


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 相关文章推荐
JavaScript中“+=”的应用
Feb 02 Javascript
javascript 实现键盘上下左右功能的小例子
Sep 15 Javascript
js中iframe调用父页面的方法
Oct 30 Javascript
JavaScript淡入淡出渐变简单实例
Aug 06 Javascript
详解JavaScript的表达式与运算符
Nov 30 Javascript
浅析AngularJS Filter用法
Dec 28 Javascript
微信小程序 WXML、WXSS 和JS介绍及详解
Oct 08 Javascript
js仿新浪微博消息发布功能
Feb 17 Javascript
javascript 日期相减-在线教程(附代码)
Aug 17 Javascript
在vue中使用公共过滤器filter的方法
Jun 26 Javascript
vue2.0实现的tab标签切换效果(内容可自定义)示例
Feb 11 Javascript
react quill中图片上传由默认转成base64改成上传到服务器的方法
Oct 30 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的超级变量$_POST获取HTML表单(HTML Form) 数据
2011/05/07 PHP
使用PHP下载CSS文件中的图片的代码
2013/09/24 PHP
jQuery 源码分析笔记(2) 变量列表
2011/05/28 Javascript
借助script进行Http跨域请求:JSONP实现原理及代码
2013/03/19 Javascript
Js控制弹窗实现在任意分辨率下居中显示
2013/08/01 Javascript
jquery表单验证框架提供的身份证验证方法(示例代码)
2013/12/27 Javascript
Asp.Net alert弹出提示信息的几种方法总结
2014/01/29 Javascript
IE下通过a实现location.href 获取referer的值
2014/09/04 Javascript
JavaScript字符串对象substring方法入门实例(用于截取字符串)
2014/10/17 Javascript
jQuery的ajax下载blob文件
2016/07/21 Javascript
AngularJS常见过滤器用法实例总结
2017/07/06 Javascript
React-Native实现ListView组件之上拉刷新实例(iOS和Android通用)
2017/07/11 Javascript
JS+CSS实现滚动数字时钟效果
2017/12/25 Javascript
基于VUE移动音乐WEBAPP跨域请求失败的解决方法
2018/01/16 Javascript
vue 实现类似淘宝星级评分的示例
2018/03/01 Javascript
详解vue 路由跳转四种方式 (带参数)
2019/04/28 Javascript
layui多图上传实现删除功能的例子
2019/09/23 Javascript
vue.js实现只能输入数字的输入框
2019/10/19 Javascript
详解Vue 单文件组件的三种写法
2020/02/19 Javascript
python+splinter自动刷新抢票功能
2018/09/25 Python
Python函数定义及传参方式详解(4种)
2019/03/18 Python
python 图像处理画一个正弦函数代码实例
2019/09/10 Python
python使用turtle库绘制奥运五环
2020/02/24 Python
Python selenium如何打包静态网页并下载
2020/08/12 Python
利用python实现汉诺塔游戏
2021/03/01 Python
整理HTML5移动端开发的常用触摸事件
2016/04/15 HTML / CSS
Python里面如何实现tuple和list的转换
2012/06/13 面试题
生物技术专业毕业生求职信范文
2013/12/14 职场文书
实习评语
2013/12/16 职场文书
工程业务员岗位职责
2013/12/31 职场文书
应届毕业生简历自我评价
2014/01/31 职场文书
写给老婆的检讨书
2014/02/21 职场文书
2014年社区工会工作总结
2014/12/18 职场文书
python基础之停用词过滤详解
2021/04/21 Python
MySQL分库分表与分区的入门指南
2021/04/22 MySQL
MySQL8.0.18配置多主一从
2021/06/21 MySQL