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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1232471.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【寒武纪(10)】linux arm aarch 是 opencv 交叉编译与使用

文章目录 1、直接找github 别人编译好的2、自主编译参考 3使用CMake检查 参考 1、直接找github 别人编译好的 测试很多&#xff0c;找到一个可用的。 https://github.com/dog-qiuqiu/libopencv 它用了超级模块&#xff01; OpenCV的world模块也称为超级模块&#xff08;supe…

NX二次开发UF_CAM_ask_opt_template_object 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;里海NX二次开发3000例专栏 UF_CAM_ask_opt_template_object Defined in: uf_cam.h int UF_CAM_ask_opt_template_object(UF_CAM_opt_t * opt_object ) overview 概述 This function provides the object which is used to in…

Python如何将项目直接打包为一键整合包

目录 一、准备项目 二、创建打包文件 三、创建安装脚本 四、执行安装 五、测试安装 六、常见问题与解决方案 总结 Python项目打包成一键整合包是一个比较复杂的任务&#xff0c;需要考虑到项目的各个方面&#xff0c;包括依赖项、配置文件、静态文件、数据库等等。下面是…

澳洲猫罐头如何?我亲自喂养过的优质猫罐头分享

猫罐头要符合三点&#xff1a;营养配方完整均衡、原料新鲜优质、生产工艺科学可靠。只有具备这些特点&#xff0c;才是品质上乘的猫罐头。 猫罐头的三个要素&#xff0c;一个都不能少。配方不均衡&#xff0c;营养就不足&#xff1b;原料不新鲜&#xff0c;生产出来的猫罐头就…

计算机毕业设计python企业员工人事管理系统vue

管理员&#xff1a; 1.员工资料管理&#xff1a;查看员工列表&#xff0c;添加职工&#xff0c;修改信息&#xff08;搜索员工使用模糊查询&#xff09; 2.部门管理&#xff1a;查看部门列表&#xff0c;修改信息&#xff0c;添加新部门 3.职工考勤管理&#xff1a;添加&#x…

vue3-响应式核心

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue3-响应式核心 响应式核心 目录 响应式核心 3.1ref() 3.2computed () 3.3 reactive() 3.4 …

[C++ 从入门到精通] 12.重载运算符、赋值运算符重载、析构函数

&#x1f4e2;博客主页&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;本文由 丶布布原创&#xff0c;首发于 CSDN&#xff0c;转载注明出处&#x1f649;&#x1f4e2;现…

SAP创建权限对象、角色、并分配角色

一、SU20&#xff1a;维护权限字段 二、SU21创建权限对象,分配权限字段: 三、SU24关联程序和自建权限对象&#xff08;标准tcode会默认存在标准权限对象&#xff09; 四、PFCG创建角色 五、SU01给用户分配角色 一、su20&#xff1a;维护权限字段 X点新建&#xff1a; 填入…

智慧化工园区信息化整体解决方案:PPT全53页,附下载

关键词&#xff1a;智慧化工园区建设方案&#xff0c;智慧化工园区建设规范&#xff0c;智慧化工园区建设指南 一、售智慧化工园区建设背景 随着工业化、信息化和数字化进程的加速&#xff0c;化工园区面临着越来越多的挑战&#xff0c;如安全生产、环境保护、能源消耗等问题…

NX二次开发UF_CAM_ask_post_template_name 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;里海NX二次开发3000例专栏 UF_CAM_ask_post_template_name Defined in: uf_cam.h int UF_CAM_ask_post_template_name(const char * * post_template_filename ) overview 概述 This function provides the name of the file…

EtherCAT从站EEPROM分类附加信息详解:RXPDO(输入过程数据对象)

0 工具准备 1.EtherCAT从站EEPROM数据(本文使用DE3E-556步进电机驱动器)1 分类附加信息——RXPDO(输入过程数据对象) 1.1 分类附加信息规范 在EEPROM字64开始的区域存储的是分类附加信息,这里存储了包括设备信息、SM配置、FMMU配置在内的诸多信息。每个信息在一段连续的…

全球地表水年度数据集JRC Yearly Water Classification History, v1.4数据集

简介&#xff1a; JRC Yearly Water Classification History, v1.4是一个对全球水资源进行分类的数据集&#xff0c;覆盖了1984年至2019年的时间范围。该数据集是由欧盟联合研究中心&#xff08;JRC&#xff09;开发的&#xff0c;使用的数据源是来自Landsat系列卫星的高分辨率…

NX二次开发UF_CAM_ask_tool_matl_db_object 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;里海NX二次开发3000例专栏 UF_CAM_ask_tool_matl_db_object Defined in: uf_cam.h int UF_CAM_ask_tool_matl_db_object(UF_CAM_db_object_t * db_obj ) overview 概述 This function provides the database object which is…

Ubuntu本地快速搭建web小游戏网站,公网用户远程访问

前言 网&#xff1a;我们通常说的是互联网&#xff1b;站&#xff1a;可以理解成在互联网上的一个房子。把互联网看做一个城市&#xff0c;城市里面的每一个房子就是一个站点&#xff0c;房子里面放着你的资源&#xff0c;那如果有人想要访问你房子里面的东西怎么办&#xff1…

BUUCTF 菜刀666 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 流量分析&#xff0c;你能找到flag吗 注意&#xff1a;得到的 flag 请包上 flag{} 提交 密文&#xff1a; 下载附件&#xff0c;解压得到一个.pcapng文件。 解题思路&#xff1a; 1、双击文件&#xff0c;打开wir…

C语言——I /深入理解指针(一)

一、内存和地址 1byte&#xff08;字节&#xff09; 8bit&#xff08;比特位&#xff09; 1KB 1024byte 1MB 1024KB 1GB 1024MB 1TB 1024GB 1PB 1024TB一个比特位可以存放二进制的0/1的一位 ⽣活中我们把⻔牌号也叫地址&#xff0c;在计算机中我们把内存单元的编号也称为…

初步设计报告(框架)

前言 &#xff08;简述初步设计报告编制的背景、过程及其它有关情况&#xff09;&#xff08;内容可根据项目的实际建设内容进行选择&#xff09; 编制单位资质证明

DBS note3:B+ Trees

目录 1、介绍 2、B树特征 3、插入 4、删除 5、存储记录 1&#xff09;方法1&#xff1a;按值存储 2&#xff09;方法2&#xff1a;按引用存储 3&#xff09;方法3&#xff1a;按引用列表存储 6、聚类&#xff08;Clustering&#xff09; 1&#xff09;非聚类&#xff…

在 OpenCV 中使用 ChArUco 棋盘

TLDR&#xff1a;目前在线的许多 Charuco 示例代码都已过时&#xff0c;并且会让你出错。如果 ChatGPT 或 Stack Exchange 建议你使用&#xff1a;cv2.aruco.CharucoBoard_create(length, width, ...)你会发现正确的语法是 cv2.aruco.CharucoBoard((length, width), ...)。希望…

vs code git问题:文件明明已加入忽略文件中,还是出现

vs code git问题&#xff1a;文件明明已加入忽略文件中&#xff0c;还是出现 原因&#xff1a; 因为之前这些文件都已经提交过&#xff0c;线上GIT已经存在&#xff0c;已存在就不能忽略&#xff0c; 解决办法&#xff1a; 先要删除这些文件提交上去&#xff0c;然后把这些文…