【DOM笔记三】节点操作(节点概述、节点层级、添加 / 删除 / 复制节点、DOM基本语法总结!

2023-12-20 15:28:11

5 节点操作

获取元素的方式:

image-20231219145956719

比较发现,用节点层级关系来获取元素更简单(DOM方法相当于绝对路径,节点方法相当于相对路径)。

5.1 节点概述

**概念:**网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示。

**基本组成:**nodeType(节点类型) 、nodeName(节点名称)、nodeValue(节点值)

  • 元素节点nodeType为1
  • 属性节点nodeType为2
  • 文本节点nodeType为3(文本节点包含文字、空格、换行等)

**节点操作(主要为元素节点)的目的:**获取元素

5.2 节点层级

利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄层级关系

5.2.1 父子节点
image-20231219150855037

1.父节点

  • node.parentNode

2.子节点

  • node.childNodes(标准),返回子节点(元素节点、文本节点…)集合
  • node.children(非标准),返回子元素节点集合(各浏览器都支持,更常用
  • node.firstChild,返回第一个子节点(所有类型),找不到返回null
  • node.lastChild,返回最后一个子节点(所有类型)
  • node.firstElementChild,返回第一个子元素节点,IE9以上才支持
  • node.lastElementChild,返回最后一个子元素节点,IE9以上才支持
  • node.children[0],返回第一个子元素节点,没有兼容性问题
  • node.children[ol.children.length - 1]),返回ol最后一个子元素节点,没有兼容性问题
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <!-- 节点的优点 -->
    <div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <ol>
        <li>我是li1</li>
        <li>我是li2</li>
        <li>我是li3</li>
        <li>我是li4</li>
    </ol>
    
    <div class="demo">
        <div class="box">
            <span class="erweima">×</span>
        </div>
    </div>
    
    <script>
        // DOM 提供的方法(API)获取 '父节点'
        var erweima = document.querySelector('.erweima');
        var box = document.querySelector('.box');  // 以前获得.box方法
        // 父节点 node.parentNode
        console.log(erweima.parentNode);   // 现在获得.box方法为erweima.parentNode,返回<div class="box">...</div>,得到的是离元素最近的父级节点(亲爸爸)box,得不到demo,如果找不到父节点就返回为 null
        
        
        // DOM 提供的方法(API)获取 '子节点'
        var ul = document.querySelector('ul');
        var lis = ul.querySelectorAll('li');
        // 1. node.childNodes 获得所有的子节点,包含:元素节点、文本节点...
        console.log(ul.childNodes);  // NodeList(9)
        console.log(ul.childNodes[0].nodeType);  // 3(文本节点)
        console.log(ul.childNodes[1].nodeType);  // 1(元素节点)
        // 如何只获取元素节点?
        var ul = document.queryselector ('ul');
		for(var i = 0; i < ul.childNodes.length; i++) {
			if (ul.childNodes[i].nodeType == 1) {
				console.log (ul.childNodes[i]);	 // ul.childNodes[i]是元素节点
            }
		}   // 这种方法太麻烦,因此用方法2

        // 2. node.children 获取所有的子元素节点,更常用
        console.log(ul.children);  // HTMLCollection(4)
        
        
        var ol = document.querySelector('ol');
        // 3.4. node.firstChild 
        console.log(ol.firstChild);  // #text
        console.log(ol.lastChild);  // #text
        // 5.6. node.firstElementChild,IE9以上才支持
        console.log(ol.firstElementChild);  // <li>我是li1</li>
        console.log(ol.lastElementChild);   // <li>我是li4</li>
        // 7.8. node.children[0]实际开发的写法,没有兼容性问题
        console.log(ol.children[0]);  // <li>我是li1</li>
        console.log(ol.children[ol.children.length - 1]);  // <li>我是li4</li>
    </script>
</body>

</html>

案例:下拉菜单

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        li {
            list-style-type: none;
        }
        
        a {
            text-decoration: none;
            font-size: 14px;
        }
        
        .nav {
            margin: 100px;
        }
        
        .nav>li {
            position: relative;
            float: left;
            width: 80px;
            height: 41px;
            text-align: center;
        }
        
        .nav li a {
            display: block;
            width: 100%;
            height: 100%;
            line-height: 41px;
            color: #333;
        }
        
        .nav>li>a:hover {
            background-color: #eee;
        }
        
        .nav ul {
            display: none;
            position: absolute;
            top: 41px;
            left: 0;
            width: 100%;
            border-left: 1px solid #FECC5B;
            border-right: 1px solid #FECC5B;
        }
        
        .nav ul li {
            border-bottom: 1px solid #FECC5B;
        }
        
        .nav ul li a:hover {
            background-color: #FFF5DA;
        }
    </style>
</head>

<body>
    <ul class="nav">
        <li>
            <a href="#">微博</a>
            <ul>
                <li>
                    <a href="">私信</a>
                </li>
                <li>
                    <a href="">评论</a>
                </li>
                <li>
                    <a href="">@我</a>
                </li>
            </ul>
        </li>
        <li>
            <a href="#">微博</a>
            <ul>
                <li>
                    <a href="">私信</a>
                </li>
                <li>
                    <a href="">评论</a>
                </li>
                <li>
                    <a href="">@我</a>
                </li>
            </ul>
        </li>
        <li>
            <a href="#">微博</a>
            <ul>
                <li>
                    <a href="">私信</a>
                </li>
                <li>
                    <a href="">评论</a>
                </li>
                <li>
                    <a href="">@我</a>
                </li>
            </ul>
        </li>
        <li>
            <a href="#">微博</a>
            <ul>
                <li>
                    <a href="">私信</a>
                </li>
                <li>
                    <a href="">评论</a>
                </li>
                <li>
                    <a href="">@我</a>
                </li>
            </ul>
        </li>
    </ul>
    <script>
        // 1. 获取元素
        var nav = document.querySelector('.nav');
        var lis = nav.children; // 得到4个小li
        // 2.循环注册事件
        for (var i = 0; i < lis.length; i++) {
            lis[i].onmouseover = function() {
                this.children[1].style.display = 'block';
            }
            lis[i].onmouseout = function() {
                this.children[1].style.display = 'none';
            }
        }
    </script>
</body>

</html>

鼠标指向菜单后出现下拉菜单,离开后自动隐藏:

5.2.2 兄弟节点
  • node.nextSibling,返回元素下一个兄弟节点(所有类型),找不到返回null
  • node.previousSibling,返回元素上一个兄弟节点(所有类型),找不到返回null
  • node.nextElementSibling,返回元素下一个兄弟元素节点,找不到返回null,IE9以上才支持
  • node.previousElementSibling,返回元素上一个兄弟元素节点,找不到返回null,IE9以上才支持
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div>我是div</div>
    <span>我是span</span>
    <script>
        var div = document.querySelector('div');
        // 1.2. nextSibling 下一个兄弟节点,包含:元素节点、文本节点...
        console.log(div.nextSibling);  // #text
        console.log(div.previousSibling);  // #text
        
        // 3.4. nextElementSibling 下一个兄弟元素节点,IE9以上才支持
        console.log(div.nextElementSibling);  // <span>我是span</span>
        console.log(div.previousElementSibling);   // null
        // 有兼容性问题怎么办?封装一个兼容性函数。
        function getNextElementsibling (element) {
            var el = element;
            while (el = el.nextsibling) {
                if (el.nodeType === 1) {   // 是元素节点就返回
                    return el;
                }
            }
            return null;
        }

    </script>
</body>

</html>

5.3 添加元素

在页面中添加元素的步骤:

  1. 创建节点
  • document.createElement('tagName'),由tagName指定的HTML元素创建。因为这些元素原先不存在,是根据我们的需求动态生成的,所以我们也称为动态创建元素节点
  1. 添加节点
  • node.appendChild(child);,将一个节点添加到指定父节点的子节点列表末尾,类似于CSS里面的after伪元素。
  • node.insertBefore(child,指定元素);将一个节点添加到指定父节点的指定子节点前面,类似于CSS里面的before伪元素。
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <ul>
        <li>123</li>
    </ul>
    <script>
        // 1. 创建节点元素节点
        var li = document.createElement('li');
        
        // 2. 添加节点node.appendChild(child),类似于数组中的push
        var ul = document.querySelector('ul');
        ul.appendChild(li); // 给ul父节点内的末尾加上小li
        
        // 3. 添加节点node.insertBefore(child, 指定元素);
        var lili = document.createElement('li');
        ul.insertBefore(lili, ul.children[0]);  // ul.children[0]为第一个孩子,在它前面插入lili
    </script>
</body>

</html>

案例:简单版-发布留言

需求:输入留言内容,点击发布后内容会出现在下面。

思路:点击按钮后动态创建一个li,添加到ul里面。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        body {
            padding: 100px;
        }
        
        textarea {
            width: 200px;
            height: 100px;
            border: 1px solid pink;
            outline: none;
            resize: none;
        }
        
        ul {
            margin-top: 50px;
        }
        
        li {
            width: 300px;
            padding: 5px;
            background-color: rgb(245, 209, 243);
            color: red;
            font-size: 14px;
            margin: 15px 0;
        }
    </style>
</head>

<body>
    <textarea name="" id=""></textarea>
    <button>发布</button>
    <ul>
		<!-- 留言板内容 -->
    </ul>
    <script>
        // 1. 获取元素
        var btn = document.querySelector('button');
        var text = document.querySelector('textarea');
        var ul = document.querySelector('ul');
        // 2. 注册事件
        btn.onclick = function() {
            if (text.value == '') {   // 用户没输入内容就提交了
                alert('您没有输入内容');
                return false;
            } else {
                // console.log(text.value);  留言的内容
                // (1) 创建元素
                var li = document.createElement('li');  // 先有li
                li.innerHTML = text.value;  // 再进行赋值
                // (2) 添加元素
                // ul.appendChild(li);   新写的留言在最后面显示
                ul.insertBefore(li, ul.children[0]);   // 新写的留言在最前面显示
            }
        }
    </script>
</body>

</html>

5.4 删除节点

  • node.removeChild(child),删除子节点并返回删除的节点
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <button>删除</button>
    <ul>
        <li>熊大</li>
        <li>熊二</li>
        <li>光头强</li>
    </ul>
    <script>
        // 1.获取元素
        var ul = document.querySelector('ul');
        var btn = document.querySelector('button');
        // 2. 删除元素  node.removeChild(child)
        // ul.removeChild(ul.children[0]);  熊大被删掉
        // 3. 点击按钮依次删除里面第一个孩子
        btn.onclick = function() {
            if (ul.children.length == 0) {
                this.disabled = true;   // 如果没有元素,按钮就被禁用
            } else {
                ul.removeChild(ul.children[0]);
            }
        }
    </script>
</body>

</html>

案例:删除留言

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        body {
            padding: 100px;
        }
        
        textarea {
            width: 200px;
            height: 100px;
            border: 1px solid pink;
            outline: none;
            resize: none;
        }
        
        ul {
            margin-top: 50px;
        }
        
        li {
            width: 300px;
            padding: 5px;
            background-color: rgb(245, 209, 243);
            color: red;
            font-size: 14px;
            margin: 15px 0;
        }
        
        li a {
            float: right;
        }
    </style>
</head>

<body>
    <textarea name="" id=""></textarea>
    <button>发布</button>
    <ul>

    </ul>
    <script>
        // 1. 获取元素
        var btn = document.querySelector('button');
        var text = document.querySelector('textarea');
        var ul = document.querySelector('ul');
        // 2. 注册事件
        btn.onclick = function() {
            if (text.value == '') {
                alert('您没有输入内容');
                return false;
            } else {
                // (1) 创建元素
                var li = document.createElement('li');
                li.innerHTML = text.value + "<a href='javascript:;'>删除</a>";  // 使用javascript:阻止链接跳转,效果比#好
                
                // (2) 添加元素
                ul.insertBefore(li, ul.children[0]);
                
                // (3) 删除元素:删除的是当前链接的li(它的父亲)
                var as = document.querySelectorAll('a');
                for (var i = 0; i < as.length; i++) {
                    as[i].onclick = function() {  
                        ul.removeChild(this.parentNode);  // node.removeChild(child); 删除的是当前a所在的li,this.parentNode;
                    }
                }
            }
        }
    </script>
</body>

</html>

5.5 复制节点

  • node.cloneNode ();,括号为空或者里面是false,为浅拷贝,只复制标签不复制里面的内容
  • node.cloneNode(true);, 括号为true,为深拷贝,复制标签里面的内容
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <ul>
        <li>1111</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        // 1. node.cloneNode(); 浅拷贝
        // 2. node.cloneNode(true); 深拷贝
        var lili = ul.children[0].cloneNode(true);
        ul.appendChild(lili);
    </script>
</body>

</html>

浅拷贝效果:image-20231219172015455 深拷贝效果:

案例:动态生成表格

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        table {
            width: 500px;
            margin: 100px auto;
            border-collapse: collapse;
            text-align: center;
        }
        
        td,
        th {
            border: 1px solid #333;
        }
        
        thead tr {
            height: 40px;
            background-color: #ccc;
        }
    </style>
</head>

<body>
    <table cellspacing="0">
        <thead>
            <tr>
                <th>姓名</th>
                <th>科目</th>
                <th>成绩</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>
         <!-- 放准备好的学生数据,一个学生放一行 -->
        </tbody>
    </table>
    <script>
        // 1.先准备好学生的数据(实际应用:JS动态生成,从数据库中取数据;此处:模拟数据)
        var datas = [{    // 一个数组中放了多个对象
            name: '魏璎珞',
            subject: 'JavaScript',
            score: 100
        }, {
            name: '弘历',
            subject: 'JavaScript',
            score: 98
        }, {
            name: '傅恒',
            subject: 'JavaScript',
            score: 99
        }, {
            name: '明玉',
            subject: 'JavaScript',
            score: 88
        }];
        
        // 2. 往tbody里面创建行:有几个人(看数组的长度)就创建几行
        var tbody = document.querySelector('tbody');
        for (var i = 0; i < datas.length; i++) { // 外面的for循环指行 tr
            var tr = document.createElement('tr');  // 创建tr行
            tbody.appendChild(tr);
            // 行里面创建3个单元格td  for循环遍历对象 datas[i]
            for (var k in datas[i]) {   // 里面的for循环指列 td
                var td = document.createElement('td');    // 创建单元格 
                td.innerHTML = datas[i][k];  // 把对象里面的属性值datas[i][k] 给td 
                tr.appendChild(td);
            }
            // 3. 创建删除列单元格 
            var td = document.createElement('td');
            td.innerHTML = '<a href="javascript:;">删除</a>';
            tr.appendChild(td);
        }
        // 4. 删除操作 开始 
        var as = document.querySelectorAll('a');
        for (var i = 0; i < as.length; i++) {
            as[i].onclick = function() {
                // 点击a,删除当前a所在的行(链接的爸爸的爸爸)  node.removeChild(child)  
                tbody.removeChild(this.parentNode.parentNode)
            }
        }
    </script>
</body>

</html>

image-20231219172418183

5.6 三种动态创建元素的区别

  • document.write(),直接将内容写入页面的内容流,但是文档流执行完毕,则它会导致页面全部重绘
  • element.innerHTML,不会导致页面全部重绘,创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
  • document.createElement(),创建多个元素效率稍低一点点,但是结构更清晰

总结:不同浏览器下,innerHTML效率要比creatElement高

6 DOM小结

  1. 创建

    • document.write

    • innerHTML

    • createElement

  2. 增加

    • appendChild

    • insertBefore

  3. 删除

    • removeChild
  4. 修改(元素属性、元素内容、表单的值…)

    • 元素属性:src、href、title等

    • 普通元素内容:innerHTML、innerText

    • 表单元素:value、type、disabled等

    • 元素样式:style、className

  5. 查询(DOM元素)

    • DOM提供的API方法:getElementByld、getElementsByTagName 古老用法不太推荐

    • H5提供的新方法:querySelector、querySelectorAll 提倡

    • 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡

  6. 属性操作(主要针对自定义属性)

    • setAttribute:设置dom的属性值

    • getAttribute:得到dom的属性值

    • removeAttribute:移除属性

  7. 事件操作(给元素注册事件,采取事件源.事件类型=事件处理程序

image-20231219191817442

文章来源:https://blog.csdn.net/waski/article/details/135101615
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。