JavaScript快速查找节点

我们在实际的开发中,经常要获取页面中某个html元素,动态更新元素的样式、内容属性等。

我们已经知道在JavaScript中提供下面的方法获取子、父、兄节点的方法:

  常规

通过父节点获取子节点:

  1. parentObj.firstChild                                            获取已知父节点的第一个子节点 
  2. parentObj.lastChild                                            获取已知父节点的最后一个子节点
  3. parentObj.childNodes                                             获取已知父节点的子节点数组(这里我在IE 7中获取的是所有直接的子节点)
  4. parentObj.children                                                 获取已知节点的直接子节点数组(在IE7中和childNodes效果一样)
  5. parentObj.getElementsByTagName(tagName)     返回已知子节点中类型为指定值的子节点数组

通过临近节点获取兄弟节点:

  1. neighbourNode.previousSibing                              获取已知节点的前一个兄弟节点
  2. neighbourNode.nextSibing 获取已知节点的下一个兄弟节点

通过子节点获取父节点:

1、childNode.parentNode                                             获取已知节点的父节点

上面的方法基本都是可以递归是使用的,parentObj.firstChild.firstChild.firstChild...但是这样的代码有一种傻傻的赶脚。。

  扩展

在扩展之前,我们需要知道一些关于节点基础的知识:Dom节点中,每个节点都拥有不同的类型

     W3C规范中常用的Dom节点的类型有以下几种

节点类型

说明

元素节点

每一个HTML标签都是一个元素节点

1

属性节点

元素节点(HTML标签)的属性,如id,class,name等

2

文本节点

元素节点或属性节点中的文本内容

3

注释节点

便是文档的注释,形式如<!--comment Text-->

8

文档节点

表示整个文档(Dom树的根节点,即document)

9

 关于节点的名称,不同类型的节点对应不同的名称

节点类型

节点名称

元素节点

HTML的名称(大写)

属性节点

属性的名称

文本节点

它的值永远的都#text

文档节点

它的值永远都是#document

可以分别通过nodeType(节点类型),nodeName(节点名称),以及nodeValue(节点值)分别返回节点的类型(比如元素节点返回1,属性节点返回2)、节点名称以及节点值;

JS获取兄弟节点的两种方法

 方法一:通过父元素的子元素先找到含自己在内的“兄弟元素”,然后在剔除自己

1 function sibling(elem){
2    var a = [];
3    var b = elem.parentNode.children;
4    for (var i = 0 ; i < b.length ; i++){
5       if(b[i] !== elem)   a.push(b[i]);
6    }
7    return a;
8 }

方法二:jQuery中实现方法,先通过查找元素的第一个子元素,然后在不断往下找下一个紧邻元素,判断并剔除自己。

 1 siblings:function(elem)
 2 {
 3      return JQuery.sibling(elem.parentNode.firstNode,elem);
 4 }
 5 
 6 JQuery.sibling = function(n,elem){
 7       var r = [];
 8        for (;n;n= n.nextSibling){
 9        if(n.nodeType == 1 && (!elem ||  elem  != elem))
10         r.push(n);
11     }  
12      return r;
13 }

在jQuery 1.2多的版本中都可以找到这段代码,我看的jQuery1.2.3的版本,在1800行可以找到这段代码:

把这个方法转化为独立可用的函数:

 1 fucntion sibling(elem){
 2     var r = [];
 3     var n = elem.parentNode.firstChild;
 4     for(;n;n = n.nextSibling) {
 5         if(n.nodeType === 1 && n !== elem) {
 6             r.push(n);
 7         }
 8     }  
 9      return r;
10 }

很显然通过这种方法查找特定节点的兄弟元素,可以很方便的避免的使用递归的冗余。

获取所有元素子节点

 在JavaScript中,可以通过children来获取所有的子节点(只返回HTML中,甚至不返回子节点),几乎得到了所有浏览器的支持,但是在Firefox有的版本中不支持。

注意:在IE中,children包含注释节点

所以因为特殊情况的存在,有时候我们需要只获取元素节点,这样我们就可以通过nodeType属性来进行筛选,用上面的知识:nodeType == 1的节点为元素节点。

下面,自定义一个函数来获取所有的元素子节点:

 1 var getChildNodes = function(elem) {
 2     var childArr = elem.children || elem.childNodes,  
 3           childArrTem = new Array();
 4      for (var i = 0 ; i < childArr.length; i ++ )  {
 5            if (childArr[i].nodeType == 1){
 6            childArrTem.push(childArr[i]); 
 7       }
 8    } 
 9    return childArrTem;
10 }

   获取所有的父节点

同样的,我们可以获取当前节点所有的父节点:

1 function getParents (elem){
2   var parents = [];
3    while(elem.parentNode){
4        parents.push(elem.parentNode)
5        elem = elem.parentNode;
6    } 
7     return parents;
8 }

这样我们可以接受一个dom节点,最终会获取到document对象,如果只要获取到最上层是body,可以把while里的判断改为:  while(elem.parentNode && elem.parentNode.tagName == 'BODY'

依据JavaScript中的提供的获取节点的方法和相关的知识,我们可以写出很多封装的方法,尝试一下,你可以写出多少种获取节点的方法呢?

当我们写出了一些操作节点的封装之后在去看jQuery中Dom操作节点方法的源码会轻松很多呢。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏朱慕之的博客

基础算法

0.创建类 BinaryTreeNode 1.创建方法:传入根结点 2.判断根节点是否为空 3.判断左右结点是否同时为空 4.用self调用此方法,将根节点的左...

591
来自专栏一个会写诗的程序员的博客

第2章 Kotlin 语法基础第2章 Kotlin 语法基础

人与人之间通过语言来交流沟通,互相协作。人与计算机之间怎样“交流沟通”呢?答案是编程语言。一门语言有词、短语、句子、文章等,对应到编程语言中就是关键字、标识符、...

1002
来自专栏Python小屋

Python版选择排序算法

关于Python版冒泡排序算法请参考:Python版冒泡法排序算法。 def selectSort(lst, reverse=False): leng...

2585
来自专栏web前端

CSS3---first-child或者nth-child(1) 不起作用的原因

一、零碎      1、first-child、last-child、nth-child(n)、nth-child(2n)、nth-child(2n-1)、nt...

2215
来自专栏和蔼的张星的图像处理专栏

64. 合并排序数组 II 三指针+从后向前

合并两个排序的整数数组A和B变成一个新的数组。 注意事项 你可以假设A具有足够的空间(A数组的大小大于或等于m+n)去添加B中的元素。 样例 给出A =...

821
来自专栏mathor

LeetCode42. 接雨水

 有人说用贪心,我觉得这是一个单调栈的板子题,构建一个单调递减栈(栈底到栈顶是递减的),要想能够收集雨水,栈中至少要两个数字,才能形成一个坑,先pop一个数...

1022
来自专栏青玉伏案

算法与数据结构(十五) 归并排序(Swift 3.0版)

上篇博客我们主要聊了堆排序的相关内容,本篇博客,我们就来聊一下归并排序的相关内容。归并排序主要用了分治法的思想,在归并排序中,将我们需要排序的数组进行拆分,将其...

1825
来自专栏日常学python

Python最容易掉进去的10个坑

相比于其他语言,Python的语法比较简单易学,但一旦不注意细节,刚入门的新手很容易就会掉进语法错误的坑里。

493
来自专栏GreenLeaves

JavaScript之获取和设置元素属性

1.与我前面的随笔获取元素的那些方法不同http://www.cnblogs.com/GreenLeaves/p/5689075.html 获取元素属性的方法g...

18810
来自专栏老司机的技术博客

宝宝都能学会的python编程教程14:高级特性1

切片 取一个list或tuple的部分元素是非常常见的操作。比如,一个list如下: >>> L = ['Michael', 'Sarah', 'Tracy'...

3095

扫码关注云+社区