第一章:DOM简介

1.1 什么是DOM?

  • 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口
  • W3C已经定义了一系列的DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。

1.2 DOM树

DOM树.png

  • 文档:一个页面就是一个文档,DOM中使用document表示。
  • 元素:页面中的所有标签都是元素,DOM中使用element表示。
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示。

注意:DOM将以上内容都看做是对象。

第二章:获取元素

2.1 如何获取页面元素?

  • DOM在我们实际开发中主要用来操作元素,那么我们如何来获取页面中的元素?
  • 获取页面中的元素可以使用以下几种方式:
    • ①根据ID获取。
    • ②根据标签名获取。
    • ③通过HTML5新增的方式获取。
    • ④特殊元素获取。

2.2 根据ID获取元素

  • 使用getElementById()方法可以获取带有ID的元素对象。
  1. document.getElementById('id');
  • 使用console.dir()可以打印我们获取的元素对象,更好的查看对象里面的属性和方法。

  • 示例:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>根据ID获取元素</title>
  8. </head>
  9. <body>
  10. <div id="time">2021-11-11</div>
  11. <script>
  12. // 因为文档页面从上往下架子啊,所以必须先有标签。
  13. // 参数 id是大小敏感的字符串
  14. // 返回的是一个元素对象
  15. var time = document.getElementById('time');
  16. console.log(time);
  17. console.log(typeof time); //object
  18. // console.dir() 可以打印元素对象,更好的查看里面的属性和方法
  19. console.dir(time);
  20. </script>
  21. </body>
  22. </html>

2.3 根据标签名获取元素

  • 使用getElementsByTagName()方法可以返回带有指定标签名的对象集合
document.getElementsByTagName('标签名');

注意:

  • 因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历。
  • 得到元素对象是动态的。
  • 如果获取不到元素,则返回为空的伪数组(因为获取不到的对象)。
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>根据标签名获取元素</title>
</head>

<body>
    <ul>
        <li>知否知否,应是绿肥红瘦1</li>
        <li>知否知否,应是绿肥红瘦2</li>
        <li>知否知否,应是绿肥红瘦3</li>
        <li>知否知否,应是绿肥红瘦4</li>
        <li>知否知否,应是绿肥红瘦5</li>
    </ul>
    <script>
        // 返回的是 元素对象的集合,以伪数组的存储的。
        var lis = document.getElementsByTagName('li');
        console.log(lis);
        console.log(lis[0]);

        console.log('------------------------')

        // 我们想要依次打印里面的元素对象,可以采取遍历的方式
        for (var i = 0; i < lis.length; i++) {
            console.log(lis[i]);
        }

        // 如果页面中只有一个li,返回的还是伪数组的形式。

        // 如果页面中没有这个元素,返回的是空的伪数字。
    </script>
</body>

</html>

2.4 获取某个元素(父元素)内置所有指定标签名的子元素

  • 语法:
element.getElementsByTagName('标签名');

注意:父元素必须是单个对象(必须指定是哪一个元素对象)。获取的时候不包括父元素自己。

  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title> 获取某个元素(父元素)内置所有指定标签名的子元素</title>
</head>

<body>
    <ul>
        <li>知否知否,应是绿肥红瘦1</li>
        <li>知否知否,应是绿肥红瘦2</li>
        <li>知否知否,应是绿肥红瘦3</li>
        <li>知否知否,应是绿肥红瘦4</li>
        <li>知否知否,应是绿肥红瘦5</li>
    </ul>
    <ol>
        <li>生僻字</li>
        <li>生僻字</li>
        <li>生僻字</li>
    </ol>
    <script>
        var ol = document.getElementsByTagName('ol')[0];
        // 获取某个父元素内部的所有指定标签名的子元素
        var li = ol.getElementsByTagName('li');
        for (var i = 0; i < li.length; i++) {
            console.log(li[i]);
        }
    </script>
</body>

</html>

2.5 HTML5新增获取元素的方式

  • 根据类名返回元素对象集合。
document.getElementsByClassName('类名');
  • 根据指定选择器返回第一个元素对象:
document.querySelector('选择器');
  • 根据指定选择器返回所有的元素对象:
document.querySelectorAll('选择器');

注意:querySelector和querySelectorAll里面的选择器需要加符号。

  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML5新增获取元素的方式</title>
</head>

<body>
    <div class="box">盒子</div>
    <div class="box">盒子</div>
    <div class="nav">
        <ul>
            <li>首页</li>
            <li>产品</li>
        </ul>
    </div>
    <script>
        //根据类名返回元素对象集合。
        var boxArray = document.getElementsByClassName('box');
        for (var i = 0; i < boxArray.length; i++) {
            console.log(boxArray[i]);
        }
        console.log('-----------------------------');
        //根据指定选择器返回第一个元素对象:
        var liFirst = document.querySelector('.nav ul li');
        console.log(liFirst);
        console.log('-----------------------------');
        //根据指定选择器返回所有的元素对象:
        var lis = document.querySelectorAll('.nav ul li');
        for (var i = 0; i < lis.length; i++) {
            console.log(lis[i]);
        }
    </script>
</body>

</html>

2.6 获取特殊元素(body、html)

  • 获取body元素:
document.body ;//返回body元素对象
  • 获取html元素:
document.documentElement ;//返回html元素对象
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>获取特殊元素body和html</title>
</head>

<body>
    <script>
        //获取body元素
        var bodyElement = document.body;
        console.log(bodyElement);
        //获取html元素
        var htmlElement = document.documentElement;
        console.log(htmlElement);
    </script>
</body>

</html>

第三章:事件基础

3.1 概述

  • JavaScript使我们有能力创建动态页面,而事件时可以被JavaScript侦测到的行为。
  • 简单理解:触发—响应机制。
  • 网页中的每个元素都可以产生某些可以触发JavaScript的事件。例如,我们可以在有用户点击某按钮时产生一个事件,然后去执行某些操作。

3.2 事件三要素

  • 事件源(谁)。
  • 事件类型(什么事情)。
  • 事件处理程序(做啥)。

  • 示例:

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>事件三要素</title>
</head>

<body>
    <button id="btn">唐伯虎</button>
    <script>
        //点击一个按钮,弹出对话框

        // 事件是有三部分组成:事件源、事件类型、事件处理程序,我们也称之为事件三要素。
        // - 事件源:事件被触发的对象。谁?按钮
        var btn = document.getElementById('btn');
        // - 事件类型:触发什么事件,比如鼠标点击(onclick)、鼠标经过、键盘按下。
        // - 事件处理程序:是通过一个函数赋值的方式完成
        btn.onclick = function () {
            alert('~~点秋香~~');
        }
    </script>
</body>

</html>

3.3 执行事件的步骤

  • ①获取事件源。
  • ②注册事件(绑定事件)。
  • ③添加事件处理程序(采取函数赋值的形式)。

  • 示例:

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>执行事件步骤</title>
</head>

<body>
    <div>123</div>
    <script>
        /*
        * - ①获取事件源。
        * - ②注册事件(绑定事件)。
        * - ③添加事件处理程序(采取函数赋值的形式)。
        */

        //点击div,控制台输出,我被选中了
        var divElement = document.getElementsByTagName('div')[0];
        divElement.onclick = function () {
            console.log('~~我被选中了~~');
        }
    </script>
</body>

</html>

3.4 常见的鼠标事件

鼠标事件 触发条件
onclick 鼠标点击左键触发
onmouseover 鼠标经过触发
onmouseout 鼠标离开触发
onfocus 获取鼠标焦点触发
onblur 失去鼠标焦点触发
onmousemove 鼠标移动触发
onmouseup 鼠标弹起触发
onmousedown 鼠标按下触发

第四章:操作元素

4.1 概述

  • JavaScript的DOM操作可以改变网页内容、结构和样式,我们可以利用DOM操作元素来改变元素里面的内容、属性等。

注意:以下都是属性。

4.2 改变元素的内容

  • 从起始位置到终止位置的内容,会去除html标签,空格和换行。
element.innerText;
  • 从起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行。
element.innerHTML;
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>操作元素之改变元素内容</title>
    <style>
        div {
            width: 300px;
            height: 30px;
            line-height: 30px;
            color: #fff;
            background-color: pink;
        }
    </style>
</head>

<body>
    <button>显示当前的系统时间</button>
    <div>某个时间</div>
    <script>
        /* 当我们点击了按钮,div里面的文字会发生变化 */
        // 1. 获取元素
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        // 2. 注册事件
        btn.onclick = function () {
            // 改变元素内容
            div.innerText = new Date().toLocaleString();
        }
    </script>
</body>

</html>
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>innerHTML和innerText的区别</title>

</head>

<body>
    <div></div>
    <p>
        我是文字
        <span>123</span>
    </p>
    <script>
        //1. innerText 不识别HTML标签 非标准 去掉空格和换行
        var div = document.querySelector('div');
        // div.innerText = '<b>今天</b>是2021年';
        //2. innerHTML 不识别HTML标签 W3C标准 保留空格和换行
        div.innerHTML = '<b>今天</b>是2021年';
        // innerText和innerHTML可以获取元素中的内容。
        var p = document.querySelector('p');
        console.log(p.innerText);
        console.log(p.innerHTML);
    </script>
</body>

</html>

4.3 常用元素的属性操作

  • 语法:
innerText、innerHTML 改变元素内容
src、href
id、alt、title
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>操作元素之改变元素属性</title>
    <style>
        img {
            width: 200px;
        }
    </style>
</head>

<body>
    <button id="ldh">刘德华</button>
    <button id="zxy">张学友</button>
    <br>
    <br>
    <img src="images/ldh.jpg" alt="">
    <script>
        //1.获取元素
        var ldhBtn = document.querySelector('#ldh');
        var zxyBtn = document.querySelector('#zxy');
        var img = document.querySelector('img');
        //2.注册事件 处理程序
        ldhBtn.onclick = function () {
            img.src = 'images/ldh.jpg';
        }
        zxyBtn.onclick = function () {
            img.src = 'images/zxy.jpg';
        }
    </script>
</body>

</html>

4.4 表单元素的属性操作

  • 利用DOM可以操作如下表单元素的属性:
type、value、checked、selected、disabled
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>操作元素之表单属性设置</title>
</head>

<body>
    <button>按钮</button>
    <input type="text" value="输入内容">

    <script>
        // 获取元素
        var btn = document.querySelector('button');
        var input = document.querySelector('input');
        // 注册事件 处理程序
        btn.onclick = function () {
            // 表单里面的值 是通过value来修改的
            input.value = '被点击了';
            // 如果想要某个表单被禁用,不能再点击disabled,我们想要这个按钮禁用。
            this.disabled = true;
            //this 指向的是事件函数的调用者 btn
        }
    </script>
</body>

</html>

4.5 样式属性操作

  • 可以通过JS修改元素的大小、颜色、位置等样式。
element.style     行内样式操作
element.className 类名样式操作

注意:

  • JS里面的样式采取驼峰命名法,如fontSize、backgroundColor;
  • JS修改style样式操作,产生的是行内样式,CSS权重比较高。
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>显示隐藏文本框内容</title>
    <style>
        input {
            display: block;
            width: 320px;
            height: 25px;
            outline: none;
            margin: 100px auto;
            color: #999;
        }
    </style>
</head>

<body>
    <input type="text" value="手机">
    <script>
        /* 当鼠标点击文本框时,里面的默认文字隐藏,当鼠标离开文本框时,里面的文字显示。 */
        /* 首先表单需要2个新事件,获得焦点 onfocus  失去焦点 onblur
        * 如果获得焦点,判断表单里面内容是否为默认文字,如果是默认文字,就清空表单内容
        * 如果失去焦点,判断表单内容是否为空,如果为空,则表单内容改为默认文字
        */
        var input = document.querySelector('input');
        input.onfocus = function () {
            if (this.value == '手机') {
                this.value = '';
            }
        }
        input.onblur = function () {
            if (this.value == '') {
                this.value = '手机';
            }
        }
    </script>
</body>

</html>

4.6 操作元素总结

操作元素总结.jpg

4.7 自定义属性的操作

4.7.1 获取属性值

element.属性  //获取属性值
element.getAttribute('属性');

区别:

  • element.属性;获取内置属性值(元素本身自带的属性)。
  • element.getAttribute(‘属性’); 主要获取自定义的属性(标准),程序员自定义的属性。
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义属性操作</title>
</head>

<body>
    <div id="demo" index="1"></div>

    <script>
        var div = document.querySelector('div');
        //1.获取元素的属性值
        //1.1 element.属性:获取的是内置的属性值
        console.log(div.id);
        //1.2 element.getAttribute('属性'):主要获取的是自定义的属性值
        console.log(div.getAttribute('id'));
        console.log(div.getAttribute('index'));

        //2.设置元素的属性值
        //2.1 element.属性=值:设置的是内置的属性值
        div.id = 'test';
        console.log(div.id);
        //2.2 element.setAttribute('属性','值'):设置的是自定义的属性值
        div.setAttribute('id', 'demo');
        console.log(div.id);
        div.setAttribute('index', 2);
        console.log(div.getAttribute('index'));
    </script>
</body>

</html>

4.7.2 设置属性值

element.属性 = '值' //设置内置属性值
element.setAttribute('属性','值');

区别:

  • element.属性 = ‘值’; 设置内置属性值。
  • element.setAttribute(‘属性’,’值’); 主要设置自定义的属性(标准)。
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义属性操作</title>
</head>

<body>
    <div id="demo" index="1" class="nav"></div>

    <script>
        var div = document.querySelector('div');
        //1.获取元素的属性值
        //1.1 element.属性:获取的是内置的属性值
        console.log(div.id);
        //1.2 element.getAttribute('属性'):主要获取的是自定义的属性值
        console.log(div.getAttribute('id'));
        console.log(div.getAttribute('index'));

        //2.设置元素的属性值
        //2.1 element.属性=值:设置的是内置的属性值
        div.id = 'test';
        console.log(div.id);
        div.className = 'navs';
        console.log(div.className);
        //2.2 element.setAttribute('属性','值'):设置的是自定义的属性值
        div.setAttribute('id', 'demo');
        console.log(div.id);
        div.setAttribute('index', 2);
        console.log(div.getAttribute('index'));
        div.setAttribute('class', 'footer'); //class特殊,这里写的是class,而不是className
        console.log(div.getAttribute('class'));
    </script>
</body>

</html>

4.7.3 移除属性

element.removeAttribute('属性');
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义属性操作</title>
</head>

<body>
    <div id="demo" index="1" class="nav"></div>

    <script>
        var div = document.querySelector('div');
        //1.获取元素的属性值
        //1.1 element.属性:获取的是内置的属性值
        console.log(div.id);
        //1.2 element.getAttribute('属性'):主要获取的是自定义的属性值
        console.log(div.getAttribute('id'));
        console.log(div.getAttribute('index'));

        //2.设置元素的属性值
        //2.1 element.属性=值:设置的是内置的属性值
        div.id = 'test';
        console.log(div.id);
        div.className = 'navs';
        console.log(div.className);
        //2.2 element.setAttribute('属性','值'):设置的是自定义的属性值
        div.setAttribute('id', 'demo');
        console.log(div.id);
        div.setAttribute('index', 2);
        console.log(div.getAttribute('index'));
        div.setAttribute('class', 'footer'); //class特殊,这里写的是class,而不是className
        console.log(div.getAttribute('class'));

        //3.移除属性
        // element.removeAttribute('属性');
        div.removeAttribute('index');
        console.log(div.getAttribute('index')); //null
    </script>
</body>

</html>
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义属性操作</title>
</head>

<body>
    <div id="demo" index="1" class="nav"></div>

    <script>
        var div = document.querySelector('div');
        //1.获取元素的属性值
        //1.1 element.属性:获取的是内置的属性值
        console.log(div.id);
        //1.2 element.getAttribute('属性'):主要获取的是自定义的属性值
        console.log(div.getAttribute('id'));
        console.log(div.getAttribute('index'));

        //2.设置元素的属性值
        //2.1 element.属性=值:设置的是内置的属性值
        div.id = 'test';
        console.log(div.id);
        div.className = 'navs';
        console.log(div.className);
        //2.2 element.setAttribute('属性','值'):设置的是自定义的属性值
        div.setAttribute('id', 'demo');
        console.log(div.id);
        div.setAttribute('index', 2);
        console.log(div.getAttribute('index'));
        div.setAttribute('class', 'footer'); //class特殊,这里写的是class,而不是className
        console.log(div.getAttribute('class'));

        //3.移除属性
        // element.removeAttribute('属性');
        div.removeAttribute('index');
        console.log(div.getAttribute('index')); //null
    </script>
</body>

</html>

4.8 H5自定义属性

4.8.1 概述

  • 自定义属性的目的:是为了保存并使用数据,有些数据可以保存到页面中而不需要保存到数据库中
  • 自定义属性的获取是通过getAttribute(‘属性’)获取的。
  • 但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。
  • H5给我们新增了自定义属性。

4.8.2 设置H5自定义属性

  • H5规定自定义属性data-开头做为属性名并且赋值。
<div data-index=“1”></div>
element.setAttribute(‘data-index’, 2)

4.8.3 获取H5自定义属性

  • 兼容性获取:
element.getAttribute(‘data-index’);
  • H5新增获取自定义属性:
element.dataset.index
element.dataset[‘index’]

4.8.4 应用示例

  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>H5自定义属性</title>
</head>

<body>
    <!-- H5规定自定义属性data-开头做为属性名并且赋值。 -->
    <div data-index="1" data-list-name="哈哈">dd</div>

    <script>
        /* H5规定自定义属性data-开头做为属性名并且赋值。 */
        var div = document.querySelector('div');
        div.setAttribute('data-time', 20);
        // 兼容性获取:element.getAttribute(‘data-index’);
        // H5新增获取自定义属性:element.dataset.index 或 element.dataset[‘index’]
        console.log(div.getAttribute('data-index'));
        console.log(div.getAttribute('data-list-name'));
        console.log(div.dataset.time);
        // 如果自定义属性里面有多个-链接的单词,我们获取的时候采取采取驼峰命名法。
        console.log(div.dataset.listName);
        console.log(div.dataset['listName']);
    </script>
</body>

</html>

第五章:节点操作

5.1 为什么学操作节点?

  • 获取元素通常有两种方法:
    • ①利用DOM提供的方法获取元素。
      • document.getElementById();
      • document.getElementsByTagName();
      • document.querySelector();
      • ……
      • 逻辑性不强,繁琐。
    • ②利用节点层级关系获取元素。
      • 利用父子兄弟关系获取元素。
      • 逻辑性强,但是兼容性稍差。
  • 这两种方式都可以获取元素节点,后面都会使用,但是节点操作更简单。

5.2 节点的概述

  • 网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node表示。
  • HTML DOM树中的所有节点均可通过JavaScript进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除。

节点的概述.png

  • 一般的,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
    • 元素节点:nodeType=1。
    • 属性节点:nodeType=2。
    • 文本节点:nodeType=3(文本节点包含文字、空格、换行等)。
  • 我们在实际开发中,节点的操作主要操作的是元素节点

5.3 节点层次

5.3.1 概述

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

5.3.2 父节点

node.parentNode
  • parentNode属性可以返回某个节点的父节点,注意是最近的一个父节点
  • 如果指定的节点没有父节点则返回null。

  • 示例:

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点操作之父节点</title>
</head>

<body>
    <!-- 节点的优点 -->
    <div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <div class="demo">
        <div class="box">
            <div class="erweima">x</div>
        </div>
    </div>

    <script>
        // 父节点parentNode
        var erweima = document.querySelector('.erweima');
        // var box = document.querySelector('.box');
        // 得到的是离元素最近的父级节点,如果找不到父节点返回为null。
        var box = erweima.parentNode;
        console.log(box);
    </script>
</body>

</html>

5.3.3 子节点

//标准
parentNode.childNodes
  • parentNode.childNodes返回包含指定节点的子节点的集合,该集合为即时更新的集合。
  • 注意:

    • 返回值里面包含了所有的子节点,包括元素节点、文本节点等。
    • 如果想要获取里面的元素节点,则需要专门处理,所以我们一般不提倡使用childNodes
  • 示例:

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点操作之子节点</title>
</head>

<body>
    <!-- 节点的优点 -->
    <div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <div class="demo">
        <div class="box">
            <div class="erweima">x</div>
        </div>
    </div>

    <script>
        //获取子节点
        //parentNode.childNodes,不提倡使用,太麻烦
        var demo = document.querySelector('.demo');
        var childNodes = demo.childNodes;
        for (var i = 0; i < childNodes.length; i++) {
            var childNode = childNodes[i];
            //如果是元素节点
            if (childNode.nodeType == 1) {
                console.log(childNode);
            }
        }
    </script>
</body>

</html>
//非标准
parentNode.children
  • parentNode.children是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返回(重点掌握)。
  • 虽然children是一个非标准,但是得到了各个浏览器的支持,因此可以放心大胆使用。

  • 示例:

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点操作之子节点</title>
</head>

<body>
    <!-- 节点的优点 -->
    <div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <div class="demo">
        <div class="box">
            <div class="erweima">x</div>
        </div>
    </div>

    <script>
        //获取子节点
        //1. parentNode.childNodes,不提倡使用,太麻烦
        var demo = document.querySelector('.demo');
        var childNodes = demo.childNodes;
        for (var i = 0; i < childNodes.length; i++) {
            var childNode = childNodes[i];
            //如果是元素节点
            if (childNode.nodeType == 1) {
                console.log(childNode);
            }
        }
        //2. parentNode.children 提倡使用
        var children = demo.children;
        for (var i = 0; i < children.length; i++) {
            console.log(children[i]);
        }
    </script>
</body>

</html>
parentNode.firstChild
  • firstChild返回的是第一个子节点,找不到则返回null。同样,也是包含所有的节点。
parentNode.lastChild
  • lastChild返回的是最后一个子节点,找不到则返回null。同样,也是包含所有的节点。

  • 示例:

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>子节点之第一个子元素和最后一个子元素</title>
</head>

<body>
    <ol>
        <li>我是li1</li>
        <li>我是li2</li>
        <li>我是li3</li>
        <li>我是li4</li>
    </ol>

    <script>
        var ol = document.querySelector('ol');
        //firstChild 获取的是第一个子节点,不管是文本节点还是元素节点
        console.log(ol.firstChild);
        console.log(ol.lastChild);
    </script>
</body>

</html>
parentNode.firstElementChild
  • firstElementChild返回第一个子元素节点,找不到则返回null。
parentNode.lastElementChild
  • lastElementChild返回最后一个子元素节点,找不到则返回null。
  • 注意:firstElementChild和lastElementChild有兼容性问题,IE9以上才支持

  • 示例:

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>子节点之第一个子元素和最后一个子元素</title>
</head>

<body>
    <ol>
        <li>我是li1</li>
        <li>我是li2</li>
        <li>我是li3</li>
        <li>我是li4</li>
    </ol>

    <script>
        var ol = document.querySelector('ol');
        //firstChild 获取的是第一个子节点,不管是文本节点还是元素节点
        console.log(ol.firstChild);
        //lastChild 获取的是最后子节点,不管是文本节点还是元素节点
        console.log(ol.lastChild);
        //firstElementChild 返回的是第一个子元素节点,IE9+才支持
        console.log(ol.firstElementChild);
        //lastElementChild 返回的是最后一个子元素节点,IE9+才支持
        console.log(ol.lastElementChild);
    </script>
</body>

</html>
  • 实际开发中,firstChild和lastChild包含其他节点,操作不方便;而firstElementChild和lastElementChild又有兼容性问题,那么我们如何获取第一个子元素节点或者最后一个子元素节点呢?
  • 解决方案:
    • 如果想要第一个子元素节点,可以使用parentNode.children[0];
    • 如果想要最后一个子元素节点,可以使用parentNode.children[parentNode.children.length-1];
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>新浪下拉菜单</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        a {
            text-decoration: none;
        }

        li {
            list-style: none;
        }

        .nav {
            width: 800px;
            margin: 100px auto;
            background-color: pink;
        }

        .nav > li {
            position: relative;
            width: 80px;
            height: 41px;
            float: left;
        }

        .nav li a {
            display: block;
            font-size: 16px;
            width: 100%;
            height: 100%;
            line-height: 41px;
            text-align: center;
            color: #333;
        }

        .nav > li > a:hover {
            background-color: #eee;
        }

        .nav ul {
            display: none;
            position: absolute;
            top: 41px;
            left: 0;
            width: 100%;
            border: 1px solid #FECC5B;
            border-top: none;
            border-bottom: none;
        }

        .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="#">微博2</a>
            <ul>
                <li><a href="#">私信2</a></li>
                <li><a href="#">评论2</a></li>
                <li><a href="#">@我2</a></li>
            </ul>
        </li>
        <li>
            <a href="#">微博3</a>
            <ul>
                <li><a href="#">私信3</a></li>
                <li><a href="#">评论3</a></li>
                <li><a href="#">@我3</a></li>
            </ul>
        </li>
        <li>
            <a href="#">微博4</a>
            <ul>
                <li><a href="#">私信4</a></li>
                <li><a href="#">评论4</a></li>
                <li><a href="#">@我4</a></li>
            </ul>
        </li>
    </ul>

    <script>
        /*
        * 导航栏里面的li 都要有鼠标经过效果,所以需要循环注册鼠标事件
        * 核心原理: 当鼠标经过li里面的第二个孩子ul显示,当鼠标离开,则ul 隐藏
        */
        var nav = document.querySelector('.nav');
        var lis = nav.children;
        for (var i = 0; i < lis.length; i++) {
            lis[i].onmouseover = function () {
                var ul = this.children[this.children.length - 1];
                ul.style.display = 'block';
            }
            lis[i].onmouseout = function () {
                var ul = this.children[this.children.length - 1];
                ul.style.display = 'none';
            }
        }

    </script>
</body>

</html>

5.3.4 兄弟节点

node.nextSibling
  • nextSibling返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,包含所有的节点。
node.previousSibling
  • previousSibling返回当前元素的上一个兄弟元素节点,找不到则返回null。同样,包含所有的节点。
node.nextElementSibling
  • nextElementSibling返回当前元素的下一个兄弟元素节点,找不到返回null。
node.previousElementSibling
  • previousElementSibling返回当前元素的上一个兄弟元素节点,找不到返回null。

注意:nextElementSibling和previousElementSiblin方法有兼容性问题, IE9 以上才支持。

  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点操作之兄弟节点</title>
</head>

<body>
    <div>我是div</div>
    <span>我是span</span>

    <script>
        var div = document.querySelector('div');
        //nextSibling: 下一个兄弟节点,包含元素节点或文本节点等等。
        console.log(div.nextSibling);
        console.log(div.previousSibling);
        //nextElementSibling: 下一个兄弟元素节点
        console.log(div.nextElementSibling);
        console.log(div.previousElementSibling);
    </script>
</body>

</html>

5.4 创建节点

document.createElement('tagName');
  • document.createElement('tagName')方法创建由tagName指定的HTML元素,因为这些元素原先是不存在的,是根据我们的需求动态生成的,所以我们也称之为动态创建元素节点

5.5 添加节点

node.appendChild(child);
  • node.appendChild(child);方法将一个节点添加到指定父节点的子节点列表末尾。类似于CSS中after伪元素。
node.insertBefore(child,指定元素);
  • node.insertBefore(child,指定元素);方法将一个节点添加到父节点的指定子节点的前面。类似于CSS中的before伪元素。

  • 示例:

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点操作之创建和添加节点</title>
</head>

<body>
    <ul>
        <li>123</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        //创建元素节点
        var li = document.createElement('li');
        //添加节点:node.appendChild(child) node表示父级,child表示子级 追加元素,类似于数组中的push
        ul.appendChild(li);
        //添加节点,insertBefore(child,指定元素)
        var lili = document.createElement('li');
        ul.insertBefore(lili, ul.children[0]);
    </script>
</body>

</html>

5.6 删除节点

node.removeChild(child);
  • node.removeChild(child);方法从DOM中删除一个子节点,返回删除的节点。

  • 示例:

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>删除留言案例</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body {
            padding: 100px;
        }

        textarea {
            outline: none;
            width: 200px;
            height: 100px;
            border: 1px solid pink;
            resize: none;
            vertical-align: middle;
        }

        ul {
            margin-top: 50px;
        }
    </style>
</head>

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

    <script>
        /*
        * 当我们把文本域里面的值赋值给li 的时候,多添加一个删除的链接
        * 需要把所有的链接获取过来,当我们点击当前的链接的时候,删除当前链接所在的li
        * 阻止链接跳转需要添加 javascript:void(0); 或者  javascript:;
        */
        var btn = document.querySelector('button');
        var ul = document.querySelector('ul');
        var textarea = document.querySelector('textarea');
        btn.onclick = function () {
            var textareaValue = textarea.value;
            if (textareaValue) {
                //创建元素
                var li = document.createElement('li');
                //元素赋值
                li.innerHTML = textareaValue + '<a href="javascript:void(0);">删除</a>';
                //添加元素
                ul.insertBefore(li, ul.children[0]);
                //删除元素
                var as = document.querySelectorAll('a');
                for (var i = 0; i < as.length; i++) {
                    as[i].onclick = function () {
                        ul.removeChild(this.parentNode)
                    }
                }
            }
        }
    </script>
</body>

</html>
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态创建表格</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        table {
            font-size: 16px;
            width: 1200px;
            margin: 100px auto;
            border-collapse: collapse;
        }

        thead tr {
            background-color: #eee;
        }

        thead tr th {
            height: 50px;
        }

        td {
            text-align: center;
            height: 30px;
        }

        th, td {
            width: 400px;
            border: 1px solid #999;
        }
    </style>
</head>

<body>
    <table>
        <thead>
            <tr>
                <th>姓名</th>
                <th>科目</th>
                <th>成绩</th>
                <th>操作</th>
            </tr>
        </thead>
        <tbody>

        </tbody>
    </table>

    <script>
        //1. 先准备好学生的数据
        var datas = [{
            name: '魏璎珞',
            subject: 'JavaScript',
            score: 100
        }, {
            name: '弘历',
            subject: 'Java',
            score: 50
        }, {
            name: '博恒',
            subject: 'HTML',
            score: 90
        }, {
            name: '明玉',
            subject: 'CSS',
            score: 45
        }];
        //2. 向tbody中创建行
        var tbody = document.querySelector('tbody');
        for (var i = 0; i < datas.length; i++) {
            //创建行
            var tr = document.createElement('tr');
            //2. 创建单元格
            var data = datas[i];
            //行里面创建单元格td 单元格的数量取决于每个对象里面的属性的个数 for循环遍历对象
            for (var key in data) {
                var td = document.createElement('td');
                td.innerHTML = data[key];
                tr.append(td);
            }
            //3. 创建删除单元格
            var delTd = document.createElement('td');
            delTd.innerHTML = '<a href="javascript:;">删除</a>';
            tr.append(delTd);
            tbody.append(tr);
            //4. 添加删除操作
            var as = document.querySelectorAll('a');
            for (var j = 0; j < as.length; j++) {
                as[j].onclick = function () {
                    tbody.removeChild(this.parentNode.parentNode);
                }
            }
        }

    </script>
</body>

</html>

5.7 复制节点

node.cloneNode()
  • node.cloneNode()方法返回调用该方法的节点的一个副本,也称为克隆节点或拷贝节点。

注意:

  • 如果括号参数为false或空,则是浅拷贝,即只拷贝节点本身,不拷贝里面的子节点。
  • 如果括号参数为true,则是深拷贝,会复制节点本身和里面所有的子节点。
  • 示例:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>节点操作之兄弟节点</title>
</head>

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        //将第一个li复制
        var li = document.querySelector('li');
        ul.insertBefore(li.cloneNode(true), ul.children[0]);
    </script>
</body>

</html>

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

  • 三种动态创建元素的方式:
    • document.wirte()
    • element.innerHTML
    • document.createElement()
  • 三种动态创建元素的区别:
    • document.wirte()是直接将内容写入到页面的内容流中,但是文档流执行完毕,它会导致页面全部重绘
    • element.innerHTML是将内容写入到某个DOM节点,不会导致页面全部重绘。
    • element.innerHTML创建多个元素效率更高,不要用拼接字符串,采用数组形式拼接,结构稍微复杂。
    • document.createElement()创建多个元素效率稍微低一点,但是结构更清晰。
  • 总结:不同浏览器下,element.innerHTML的效率要比 document.createElement()高

第六章:DOM重点核心

6.1 概述

  • 文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口。
  • W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。
  • 对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的dom编程接口。
  • 对于HTML,dom使得html形成一棵dom树. 包含 文档、元素、节点。

DOM树.png

6.2 DOM操作

  • 关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。

6.2.1 创建

  • document.write。
  • innerHTML。
  • createElement。

6.2.2 增加

  • appendChild。
  • insertBefore。

6.2.3 删除

  • removeChild。

6.2.4 修改

  • 主要修改dom的元素属性,dom元素的内容、属性, 表单的值等。
    • 修改元素属性: src、href、title等。
    • 修改普通元素内容: innerHTML 、innerText。
    • 修改表单元素: value、type、disabled等。
    • 修改元素样式: style、className

6.2.5 查询

  • 主要获取查询dom的元素。
    • DOM提供的API 方法: getElementById、getElementsByTagName,古老用法,不太推荐。
    • H5提供的新方法: querySelector、querySelectorAll,提倡。
    • 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling) 提倡

6.2.6 属性操作

  • 主要针对于自定义属性。
    • setAttribute:设置dom的属性值。
    • getAttribute:得到dom的属性值。
    • removeAttribute移除属性。

6.2.7 事件操作

  • 给元素注册事件,采取事件源.事件类型 = 事件处理程序。 | 鼠标事件 | 触发条件 | | —- | —- | | onclick | 鼠标点击左键触发 | | onmouseover | 鼠标经过触发 | | onmouseout | 鼠标离开触发 | | onfocus | 获取鼠标焦点触发 | | onblur | 失去鼠标焦点触发 | | onmousemove | 鼠标移动触发 | | onmouseup | 鼠标弹起触发 | | onmousedown | 鼠标按下触发 |