当前位置: 首页 > news >正文

〖大前端 - 基础入门三大核心之JS篇㊴〗- DOM节点的关系

  • 说明:该文属于 大前端全栈架构白宝书专栏,目前阶段免费如需要项目实战或者是体系化资源,文末名片加V!
  • 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 从事过全栈研发、产品经理等工作,目前在公司担任研发部门CTO。
  • 荣誉:2022年度博客之星Top4、2023年度超级个体得主、谷歌与亚马逊开发者大会特约speaker全栈领域优质创作者

  • 🏆 白宝书系列
    • 🏅 启示录 - 攻城狮的自我修养
    • 🏅 Python全栈白宝书
    • 🏅 ChatGPT实践指南白宝书
    • 🏅 产品思维训练白宝书
    • 🏅 全域运营实战白宝书
    • 🏅 大前端全栈架构白宝书


文章目录

  • ⭐ 节点的关系
  • ⭐ 书写常见的节点关系函数

⭐ 节点的关系

DOM中的各个节点的关系如下:

关系考虑所有节点
子节点childNodes
父节点parentNode
第一个子节点firstChild
最后一个子节点lastChild
前一个兄弟节点previousSibling
后一个兄弟节点nextSibling

image-20230411101350157

注意:DOM中文本节点也属于节点,在使用节点关系时一定要注意。

在标准的W3C规范中,空文本节点也应该算作节点,但是在IE8及以前的浏览器中会有一定的兼容问题,它们不把空文本节点当作节点。

在实际工作中,页面上的一些文本节点可能会对我们的元素关系造成干扰,所以,从IE9开始支持一些“只考虑元素节点”的属性:

关系考虑所有节点只考虑元素节点
子节点childNodeschildren
父节点parentNodeparentNode(因为文本节点不可能是父节点,所以父节点只用parentNode来表示就可以了)
第一个子节点firstChildfirstElementChild
最后一个子节点lastChildlastElementChild
前一个兄弟节点previousSiblingpreviousElementSibling
后一个兄弟节点nextSiblingnextElementSibling

示例代码:

<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>

image-20230411141326123

可以看到chidNodes里面包含了文本节点(每个节点之间的换行就是文本节点),而children里面只包含元素节点。

我们之前提到过,通过获取元素节点的方法得到的是一个对象,更具体点说,应该是一个类数组对象,里面不仅包含元素节点,还可以直接通过“打点调用”的方式访问具体的某个节点。

示例代码:

//得到拥有id属性para的节点
console.log(oBox.children.para)

image-20230411141802413

再来看一些其他的节点关系的示例:

<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>

image-20230411161809469

再次强调: 使用“只包含元素节点”的属性时,一定要注意兼容性,如果产品对兼容性有很高的要求,就不能使用这种属性,而是需要通过书写一个节点关系函数的方式来实现。下面就来介绍怎么书写这样的函数。

⭐ 书写常见的节点关系函数

首先,要回忆一个知识点——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>

image-20230418145028059

相关文章:

  • 威班11月份PMP模拟考试实录
  • 2.5计划任务远程管理
  • C++引用
  • Re50:读论文 Large Language Models Struggle to Learn Long-Tail Knowledge
  • 阿里云服务器公网带宽如何修改?
  • 力扣刷题第二十七天--二叉树
  • Android Serializable / Parcelable
  • 【HCSD大咖直播】亲授大厂面试秘诀【云驻共创】
  • 代码随想录算法训练营Day36 —— 435. 无重叠区间、763.划分字母区间、56. 合并区间
  • 低代码服务商,中小型数字化软件服务商的新出路
  • echarts折线图修改特定点的颜色
  • LLM之Prompt(二):清华提出Prompt 对齐优化技术BPO
  • 键鼠自动化2.0树形结构讲解
  • Using Set Processing Effectively 有效地使用集合处理
  • electron使用better-sqlite3打包失败(electron打包有进程没有界面)
  • 【5+】跨webview多页面 触发事件(二)
  • 【个人向】《HTTP图解》阅后小结
  • 2017 前端面试准备 - 收藏集 - 掘金
  • 4. 路由到控制器 - Laravel从零开始教程
  • 4个实用的微服务测试策略
  • ECS应用管理最佳实践
  • E-HPC支持多队列管理和自动伸缩
  • Java深入 - 深入理解Java集合
  • Otto开发初探——微服务依赖管理新利器
  • PAT A1092
  • Vue2.x学习三:事件处理生命周期钩子
  • webpack入门学习手记(二)
  • 基于axios的vue插件,让http请求更简单
  • 开发基于以太坊智能合约的DApp
  • 巧用 TypeScript (一)
  • 算法---两个栈实现一个队列
  • 一个JAVA程序员成长之路分享
  • 优秀架构师必须掌握的架构思维
  • 蚂蚁金服CTO程立:真正的技术革命才刚刚开始
  • ​决定德拉瓦州地区版图的关键历史事件
  • #Java第九次作业--输入输出流和文件操作
  • #pragma 指令
  • (C语言)共用体union的用法举例
  • (done) 两个矩阵 “相似” 是什么意思?
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (Java)【深基9.例1】选举学生会
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (二)构建dubbo分布式平台-平台功能导图
  • (九)c52学习之旅-定时器
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (一)eclipse Dynamic web project 工程目录以及文件路径问题
  • (原創) 物件導向與老子思想 (OO)
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .bat文件调用java类的main方法
  • .NET CLR基本术语
  • .NET 解决重复提交问题
  • .NET/C# 使窗口永不获得焦点
  • .NET下的多线程编程—1-线程机制概述
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [Android] 修改设备访问权限