我们在实际的开发中,经常要获取页面中某个 html 元素,动态更新元素的样式、内容属性等。
我们已经知道在 JavaScript 中提供下面的方法获取子、父、兄节点的方法:
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)
方法一:通过父元素的子元素先找到含自己在内的 "兄弟元素",然后在剔除自己
- function sibling(elem) {
- var a = [];
- var b = elem.parentNode.children;
- for (var i = 0; i < b.length; i++) {
- if (b[i] !== elem) a.push(b[i]);
- }
- return a;
- }
方法二:jQuery 中实现方法,先通过查找元素的第一个子元素,然后在不断往下找下一个紧邻元素,判断并剔除自己。
- siblings:function(elem)
- {
- return JQuery.sibling(elem.parentNode.firstNode,elem);
- }
- JQuery.sibling = function(n,elem){
- var r = [];
- for (;n;n= n.nextSibling){
- if(n.nodeType == 1 && (!elem || elem != elem))
- r.push(n);
- }
- return r;
- }
在 jQuery 1.2 多的版本中都可以找到这段代码,我看的 jQuery1.2.3 的版本,在 1800 行可以找到这段代码:
把这个方法转化为独立可用的函数:
- fucntion sibling(elem) {
- var r = [];
- var n = elem.parentNode.firstChild;
- for (; n; n = n.nextSibling) {
- if (n.nodeType === 1 && n !== elem) {
- r.push(n);
- }
- }
- return r;
- }
很显然通过这种方法查找特定节点的兄弟元素,可以很方便的避免的使用递归的冗余。
在 JavaScript 中,可以通过 children 来获取所有的子节点(只返回 HTML 中,甚至不返回子节点),几乎得到了所有浏览器的支持,但是在 Firefox 有的版本中不支持。
注意:在 IE 中,children 包含注释节点
所以因为特殊情况的存在,有时候我们需要只获取元素节点,这样我们就可以通过 nodeType 属性来进行筛选,用上面的知识:nodeType == 1 的节点为元素节点。
下面,自定义一个函数来获取所有的元素子节点:
- var getChildNodes = function(elem) {
- var childArr = elem.children || elem.childNodes,
- childArrTem = new Array();
- for (var i = 0; i < childArr.length; i++) {
- if (childArr[i].nodeType == 1) {
- childArrTem.push(childArr[i]);
- }
- }
- return childArrTem;
- }
同样的,我们可以获取当前节点所有的父节点:
- function getParents (elem){
- var parents = [];
- while(elem.parentNode){
- parents.push(elem.parentNode)
- elem = elem.parentNode;
- }
- return parents;
- }
这样我们可以接受一个 dom 节点,最终会获取到 document 对象,如果只要获取到最上层是 body,可以把 while 里的判断改为: while(elem.parentNode && elem.parentNode.tagName == 'BODY'
依据 JavaScript 中的提供的获取节点的方法和相关的知识,我们可以写出很多封装的方法,尝试一下,你可以写出多少种获取节点的方法呢?
当我们写出了一些操作节点的封装之后在去看 jQuery 中 Dom 操作节点方法的源码会轻松很多呢。
来源: http://www.cnblogs.com/okaychen/p/7345494.html