- 说明:该文属于 大前端全栈架构白宝书专栏,目前阶段免费,如需要项目实战或者是体系化资源,文末名片加V!
- 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 从事过全栈研发、产品经理等工作,目前在公司担任研发部门CTO。
- 荣誉:2022年度博客之星Top4、2023年度超级个体得主、谷歌与亚马逊开发者大会特约speaker、全栈领域优质创作者。
- 🏆 白宝书系列
- 🏅 启示录 - 攻城狮的自我修养
- 🏅 Python全栈白宝书
- 🏅 ChatGPT实践指南白宝书
- 🏅 产品思维训练白宝书
- 🏅 全域运营实战白宝书
- 🏅 大前端全栈架构白宝书
文章目录
- ⭐ 节点的关系
- ⭐ 书写常见的节点关系函数
⭐ 节点的关系
DOM中的各个节点的关系如下:
关系 | 考虑所有节点 |
---|---|
子节点 | childNodes |
父节点 | parentNode |
第一个子节点 | firstChild |
最后一个子节点 | lastChild |
前一个兄弟节点 | previousSibling |
后一个兄弟节点 | nextSibling |
注意:
DOM中文本节点也属于节点
,在使用节点关系时一定要注意。
在标准的W3C规范中,空文本节点也应该算作节点
,但是在IE8及以前的浏览器中会有一定的兼容问题,它们不把空文本节点当作节点。
在实际工作中,页面上的一些文本节点可能会对我们的元素关系造成干扰,所以,从IE9
开始支持一些“只考虑元素节点”的属性:
关系 | 考虑所有节点 | 只考虑元素节点 |
---|---|---|
子节点 | childNodes | children |
父节点 | parentNode | parentNode(因为文本节点不可能是父节点,所以父节点只用parentNode来表示就可以了) |
第一个子节点 | firstChild | firstElementChild |
最后一个子节点 | lastChild | lastElementChild |
前一个兄弟节点 | previousSibling | previousElementSibling |
后一个兄弟节点 | nextSibling | nextElementSibling |
示例代码:
<body>
<div id="box">
<p>我是段落</p>
<p id="para">我是段落</p>
<p>我是段落</p>
<p>我是段落</p>
</div>
<script>
var oBox = document.getElementById('box');
var para = document.getElementById('para');
//得到div#box下所有子节点
console.log(oBox.childNodes);
//得到div#box下所有元素子节点
console.log(oBox.children)
</script>
</body>
可以看到chidNodes
里面包含了文本节点(每个节点之间的换行就是文本节点),而children
里面只包含元素节点。
我们之前提到过,通过获取元素节点的方法得到的是一个对象,更具体点说,应该是一个类数组对象,里面不仅包含元素节点,还可以直接通过“打点调用”的方式访问具体的某个节点。
示例代码:
//得到拥有id属性para的节点
console.log(oBox.children.para)
再来看一些其他的节点关系的示例:
<body>
<div id="box">
<p>我是段落1</p>
<p id="para">我是段落2</p>
<p>我是段落3</p>
<p>我是段落4</p>
</div>
<script>
var oBox = document.getElementById('box');
var para = document.getElementById('para');
//父节点
console.log(para.parentNode);
//第一个子节点(考虑所有节点)
console.log(oBox.firstChild);
//第一个子节点(只考虑元素节点,IE9开始兼容)
console.log(oBox.firstElementChild);
//最后一个子节点(考虑所有节点)
console.log(oBox.lastChild);
//最后一个子节点(只考虑元素节点,IE9开始兼容)
console.log(oBox.lastElementChild);
//前一个兄弟节点(考虑所有节点)
console.log(para.previousSibling)
//后一个兄弟节点(只考虑元素节点,IE9开始兼容)
console.log(para.nextElementSibling);
</script>
</body>
再次强调: 使用“只包含元素节点”的属性时,一定要注意兼容性,如果产品对兼容性有很高的要求,就不能使用这种属性,而是需要通过书写一个节点关系函数
的方式来实现。下面就来介绍怎么书写这样的函数。
⭐ 书写常见的节点关系函数
首先,要回忆一个知识点——nodeType属性。nodeType属性等于1时,就代表这个节点是元素节点。
-
书写一个IE6也能兼容的“寻找所有元素子节点”的函数,类似
children
的功能示例代码:
<body> <div id="box"> <p>我是段落1</p> <p id="para">我是段落2</p> <p>我是段落3</p> <p>我是段落4</p> </div> <script> var box = document.getElementById('box'); var para = document.getElementById('para'); //封装一个函数,这个函数可以返回元素的所有子元素节点(兼容到IE6),类似children的功能 function getChildren(node) { //定义一个结果数组 var children = []; //遍历元素的子节点,判断nodeType是否等于1,等于1则推入结果数组 for (var i = 0; i < node.childNodes.length; i++){ if (node.childNodes[i].nodeType == 1) { children.push(node.childNodes[i]); } } return children; } var result = getChildren(box); console.log(result); </script> </body>
-
书写一个IE6也能兼容的“寻找前一个元素兄弟节点”的函数,类似previousElementSibling的功能
<body> <div id="box"> <p>我是段落1</p> <p id="para">我是段落2</p> <p>我是段落3</p> <p>我是段落4</p> </div> <script> var box = document.getElementById('box'); var para = document.getElementById('para'); //封装一个函数,这个函数可以返回某个元素的前一个元素兄弟节点(兼容到IE6),类似previousElementSibling的功能 function getElementPreviousSibling(node) { var o = node; //使用while语句 while (o.previousSibling != null) { if (o.previousSibling.nodeType == 1) { //结束循环,找到了 return o.previousSibling; } //让o成为它的前一个节点 o = o.previousSibling; } } var result = getElementPreviousSibling(para); console.log(result); </script> </body> </html>
- 书写一个IE6也能兼容的“寻找所有元素兄弟节点”的函数,类似对previousElementSibling和nextElementSibling的功能的整合
<body>
<div id="box">
<p>我是段落1</p>
<p id="para">我是段落2</p>
<p>我是段落3</p>
<p>我是段落4</p>
</div>
<script>
var box = document.getElementById('box');
var para = document.getElementById('para');
//封装一个函数,这个函数可以返回元素的所有元素兄弟节点(兼容到IE6),类似对previousElementSibling和nextElementSibling的功能的整合
function getAllElementSibling(node) {
//前面的元素兄弟节点
var prevs = [];
//后面的元素兄弟节点
var nexts = [];
var o = node;
while (o.previousSibling != null) {
if (o.previousSibling.nodeType == 1) {
prevs.unshift(o.previousSibling);
}
o = o.previousSibling;
}
o = node;
while (o.nextSibling != null) {
if (o.nextSibling.nodeType == 1) {
nexts.push(o.nextSibling);
}
o = o.nextSibling;
}
//将两个数字进行合并然后后返回
return prevs.concat(nexts);
}
var result = getAllElementSibling(para);
console.log(result);
</script>
</body>
</html>