- 说明:该文属于 大前端全栈架构白宝书专栏,目前阶段免费,如需要项目实战或者是体系化资源,文末名片加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>