Bootstrap

JS中DOM和BOM

DOM

DOM(文档对象模型)是一个跨平台和语言独立的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。在网页浏览器中,DOM 通常表示 HTML 或 XML 文档的对象模型。DOM 将网页内容视为节点树,其中每个节点都是文档中的对象,例如元素、属性、文本等。

以下是 DOM 的一些关键点:

  • 文档:在 Web 浏览器中,文档通常是指网页,即 HTML 或 XML 文件。

  • 对象模型:对象模型是将文档内容表示为对象集合的一种方式,这些对象可以由程序代码进行操作。

  • 节点树:DOM 将文档结构表示为节点树,树中的每个节点代表文档的一部分。例如,HTML 文档中的每个元素、属性和文本都是节点。

  • 编程接口:DOM 提供了一组方法(函数)和属性(变量),允许开发人员通过 JavaScript(或其他支持的语言)操作文档。

 DOM中的节点类型

在 DOM(文档对象模型)中,节点类型是通过 nodeType 属性来区分的,每个节点类型都有一个对应的常量值。以下是一些主要的 DOM 节点类型及其对应的常量值:

  1. 元素节点(Element Node)

    • 常量值:Node.ELEMENT_NODE
    • 整数值:1
    • 示例:<div><p><a>
  2. 属性节点(Attribute Node)

    • 常量值:Node.ATTRIBUTE_NODE
    • 整数值:2
    • 示例:href in <a href="http://example.com">
  3. 文本节点(Text Node)

    • 常量值:Node.TEXT_NODE
    • 整数值:3
    • 示例:文本内容 “Hello, World!” in <p>Hello, World!</p>
  4. CDATA 节点(CDATASection Node)

    • 常量值:Node.CDATA_SECTION_NODE
    • 整数值:4
    • 示例:<![CDATA[...]]> in XML documents
  5. 实体引用节点(EntityReference Node)

    • 常量值:Node.ENTITY_REFERENCE_NODE
    • 整数值:5
    • 注:在 HTML DOM 中不常用
  6. 实体节点(Entity Node)

    • 常量值:Node.ENTITY_NODE
    • 整数值:6
    • 注:在 HTML DOM 中不常用
  7. 处理指令节点(ProcessingInstruction Node)

    • 常量值:Node.PROCESSING_INSTRUCTION_NODE
    • 整数值:7
    • 示例:处理指令,常用于 XML
  8. 注释节点(Comment Node)

    • 常量值:Node.COMMENT_NODE
    • 整数值:8
    • 示例:<!-- This is a comment -->
  9. 文档节点(Document Node)

    • 常量值:Node.DOCUMENT_NODE
    • 整数值:9
    • 示例:整个 HTML 或 XML 文档
  10. 文档类型节点(DocumentType Node)

    • 常量值:Node.DOCUMENT_TYPE_NODE
    • 整数值:10
    • 示例:<!DOCTYPE html>
  11. 文档片段节点(DocumentFragment Node)

    • 常量值:Node.DOCUMENT_FRAGMENT_NODE
    • 整数值:11
    • 示例:轻量级的文档对象,可以包含多个元素而不影响文档结构
  12. 符号节点(Notation Node)

    • 常量值:Node.NOTATION_NODE
    • 整数值:12
    • 注:在 HTML DOM 中不常用

一、节点的创建、移除和克隆

1.如何改变元素节点中的内容

改变元素节点中的内容可以使用两个相关属性:innerHTML、innerText。innerHTML属性能以HTML形式设置节点中的内容;innerText系统属性只能以纯文本的形式设置节点中的内容。

2.创建节点

想要两步,第一步使用document.createElement()创建节点,第二步再上树,上树有两种情况,如果是在添加在最后,那就使用appendChild();如果不是,使用insertBefore。

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="box">
        <p>我是原本的段落0</p>
        <p>我是原本的段落1</p>
        <p>我是原本的段落2</p>
    </div>
    <script>
        var oBox = document.getElementById('box');
        var oPs = oBox.getElementsByTagName('p');

        // 创建孤儿节点
        var oP = document.createElement('p');
        // 设置内部文字
        oP.innerText = '我是新来的';
        
        // 上树
        // oBox.appendChild(oP);
        oBox.insertBefore(oP, oPs[0]);
    </script>
</body>

</html>

创建出一个20行12列的表格

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        td {
            width: 20px;
            height: 20px;
            border: 1px solid #000;
        }
    </style>
</head>

<body>
    <table id="mytable"></table>

    <script>
        // 请动态创建出一个20行12列的表格
        var mytable = document.getElementById('mytable');

        for (var i = 0; i < 20; i++) {
            // 创建了新的tr标签
            var tr = document.createElement('tr');
            for (var j = 0; j < 12; j++) {
                // 创建了新的td标签
                var td = document.createElement('td');
                // 让tr追加td标签
                tr.appendChild(td);
            }
            // 让mytable追加tr标签
            mytable.appendChild(tr);
        }
    </script>
</body>

</html>

创建9*9乘法表

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        td {
            width: 120px;
            height: 30px;
            border: 1px solid #000;
        }
    </style>
</head>

<body>
    <table id="mytable"></table>

    <script>
        // 请创建九九乘法表
        var mytable = document.getElementById('mytable');

        for (var i = 1; i <= 9; i++) {
            // 创建了新的tr标签
            var tr = document.createElement('tr');
            for (var j = 1; j <= i; j++) {
                // 创建了新的td标签
                var td = document.createElement('td');
                // 设置td内部的文字
                td.innerText = i + '乘' + j + '等于' + (i * j);
                // 让tr追加td标签
                tr.appendChild(td);
            }
            // 让mytable追加tr标签
            mytable.appendChild(tr);
        }
    </script>
</body>

</html>

 3.移动节点

如果将已经挂载到DOM树上的节点成为appendChild()或者insertBefore()的参数,这个节点将被移动。新父节点.appendChild(已经有父亲的节点);新父节点.insertBefore(已经有父亲的节点,标杆子节点);这意味着一个节点不能同时位于DOM树的两个位置。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="box1">
        <p id="para">我是段落</p>
    </div>

    <div id="box2">
        <p>我是box2的原有p标签</p>
        <p>我是box2的原有p标签</p>
        <p>我是box2的原有p标签</p>
        <p>我是box2的原有p标签</p>
    </div>

    <script>
        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var para = document.getElementById('para');
        var ps_inbox2 = box2.getElementsByTagName('p');

        // box2.appendChild(para);
        box2.insertBefore(para, ps_inbox2[0]);
    </script>
</body>
</html>

4.删除节点

removeChild()方法从DOM中删除一个字节点 父节点.removeChild(要删除子节点);子节点不能主动删除自己,必须由父节点删除它。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="box">
        <p>我是p节点0</p>
        <p>我是p节点1</p>
        <p>我是p节点2</p>
    </div>

    <script>
        var box = document.getElementById('box');
        var the_first_p = box.getElementsByTagName('p')[0];

        box.removeChild(the_first_p);
    </script>
</body>
</html>

5.克隆节点

cloneNode()方法可以克隆节点,克隆出的节点上“孤儿节点”。

var 孤儿节点=老节点.cloneNode();

var 孤儿节点=老节点.cloneNode(true);

参数是一个布尔值,表示是否采用深度克隆;如果为true,则该节点的所有后代节点也都会被克隆,如果为false,则只克隆该节点本身。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="box1">
        <ul>
            <li>牛奶</li>
            <li>咖啡</li>
            <li>可乐</li>
        </ul>
    </div>

    <div id="box2"></div>

    <script>
        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        var theul = box1.getElementsByTagName('ul')[0];

        // 克隆节点
        var new_ul = theul.cloneNode(true);
        box2.appendChild(new_ul);
    </script>
</body>
</html>

6.JS修改样式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .box{
            width: 200px;
            height: 200px;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <div class="box" id="box">
        你好
    </div>

    <script>
        var oBox = document.getElementById('box');

        // oBox.style.backgroundColor = 'rgb(100, 200, 123)';
        // oBox.style.backgroundColor = '#f80';

        // oBox.style.backgroundImage = 'url(https://www.imooc.com/static/img/index/logo-recommended.png)';
        // oBox.style.backgroundSize = 'contain';

        oBox.style.fontSize = '50px';
    </script>
</body>
</html>

 7.nodeType常用属性值

8.访问元素节点

注意:如果有多个id相同的元素 只能找到第一个。 无论id多深,都能找到。

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <div id="box1">我是盒子1</div>
    <div id="box2">我是盒子2</div>

    <script>
        
            // 得到盒子1
            var box1 = document.getElementById('box1');
            // 得到盒子2
            var box2 = document.getElementById('box2');

            console.log(box1);
            console.log(box2);
        
    </script>
</body>

</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="box1">
        <p>我是段落</p>
        <p>我是段落</p>
        <p>我是段落</p>
        <p>我是段落</p>
    </div>
    <div id="box2">
        <p>我是段落</p>
        <p>我是段落</p>
        <p>我是段落</p>
        <p>我是段落</p>
    </div>
   
    <script>
        // 先得到box1
        var box1 = document.getElementById('box1');
        // 得到box1中的p标签的数组
        var ps_inbox1 = box1.getElementsByTagName('p');

        console.log(ps_inbox1);
    </script>
</body>
</html>

9.延迟运行

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        // 给window对象添加onload事件监听。onload表示页面都加载完毕了。
        window.onload = function () {
            // 得到盒子1
            var box1 = document.getElementById('box1');
            // 得到盒子2
            var box2 = document.getElementById('box2');

            console.log(box1);
            console.log(box2);
        };
    </script>
</head>

<body>
    <div id="box1">我是盒子1</div>
    <div id="box2">我是盒子2</div>
</body>

</html>

 10.querySelector()

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="box">
        <p>我是段落</p>
        <p class="spec para">我是段落</p>
        <p>我是段落</p>
    </div>
    <script>
        var the_p = document.querySelector('#box p:nth-child(1)');
        console.log(the_p);
        
    </script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul id="list1">
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <ul id="list2">
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <script>
        var lis_inlist1 = document.querySelectorAll('#list1 li');

        console.log(lis_inlist1);
    </script>
</body>
</html>

11.节点的关系

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="box">
        <p>我是段落A</p>
        <p id="para">我是段落B</p>
        <p>我是段落C</p>
    </div>

    <script>
        var box = document.getElementById('box');
        var para = document.getElementById('para');

        // 所有子节点
        console.log(box.childNodes);
        // 所有的元素子节点(IE9开始兼容)
        console.log(box.children);
        
        // 第一个子节点
        console.log(box.firstChild);
        console.log(box.firstChild.nodeType);//子节点的类型,它是一个数
        // 第一个元素子节点(IE9开始兼容)
        console.log(box.firstElementChild);
        
        // 最后一个子节点
        console.log(box.lastChild);
        console.log(box.lastChild.nodeType);//子节点的类型,它是一个数
        // 最后一个元素子节点(IE9开始兼容)
        console.log(box.lastElementChild);

        // 父节点
        console.log(para.parentNode);
        
        // 前一个兄弟节点
        console.log(para.previousSibling);
        // 前一个元素兄弟节点(IE9开始兼容)
        console.log(para.previousElementSibling);
        
        // 后一个兄弟节点
        console.log(para.nextSibling);
        // 后一个元素兄弟节点(IE9开始兼容)
        console.log(para.nextElementSibling);
    </script>
</body>
</html>

12.常见的节点关系函数

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="box">
        <p>我是段落</p>
        <p>我是段落</p>
        <p>我是段落</p>
        <p id="fpara">我是段落fpara</p>
        我是文本
        <!-- 我是注释 -->
        <p id="para">
            我是段落para
            <span>1</span>
            <span>2</span>
            <span>3</span>
        </p>
        <p>我是段落</p>
        <p>我是段落</p>
        <p>我是段落</p>
    </div>

    <script>
        var box = document.getElementById('box');
        var para = document.getElementById('para');
        var fpara = document.getElementById('fpara');

        // 封装一个函数,这个函数可以返回元素的所有子元素节点(兼容到IE6),类似children的功能
        function getChildren(node) {
            // 结果数组
            var children = [];
            // 遍历node这个节点的所有子节点,判断每一个子节点的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;
        }

        console.log(getChildren(box));
        console.log(getChildren(para));

        // 封装一个函数,这个函数可以返回元素的前一个元素兄弟节点(兼容到IE6),类似previousElementSibling的功能
        function getElementPrevSibling(node) {
            var o = node;
            // 使用while语句
            while (o.previousSibling != null) {
                if (o.previousSibling.nodeType == 1) {
                    // 结束循环,找到了
                    return o.previousSibling;
                }

                // 让o成为它的前一个节点,就有点“递归”的感觉
                o = o.previousSibling;
            }
            return null;
        }

        console.log(getElementPrevSibling(para));
        console.log(getElementPrevSibling(fpara));

        // 封装第三个函数,这个函数可以返回元素的所有元素兄弟节点
        function getAllElementSibling(node) {
            // 前面的元素兄弟节点
            var prevs = [];
            // 后面的元素兄弟节点
            var nexts = [];
            
            var o = node;
            // 遍历node的前面的节点
            while(o.previousSibling != null) {
                if(o.previousSibling.nodeType == 1){
                    prevs.unshift(o.previousSibling);
                }
                o = o.previousSibling;
            }

            o = node;

            // 遍历node的后面的节点
            while(o.nextSibling != null) {
                if(o.nextSibling.nodeType == 1){
                    nexts.push(o.nextSibling);
                }
                o = o.nextSibling;
            }

            // 将两个数组进行合并,然后返回
            return prevs.concat(nexts);
        }

        console.log(getAllElementSibling(para));
    </script>
</body>

</html>

二、DOM事件

事件监听、事件传播、事件对象、事件委托

1. 事件监听

1.常见的鼠标事件监听

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: #333;
        }
    </style>
</head>
<body>
    <div id="box"></div>
    
    <script>
        var oBox = document.getElementById('box');

        oBox.onclick = function() {
            console.log('我是onclick');
        };

        oBox.ondblclick = function() {
            console.log('我是ondblclick');
        };

        oBox.onmousedown = function() {
            console.log('我是onmousedown');
        };

        oBox.onmouseup = function() {
            console.log('我是onmouseup');
        };

        oBox.onmouseenter = function() {
            console.log('我是onmouseenter');
        };

        oBox.onmouseleave = function() {
            console.log('我是onmouseleave');
        };

        oBox.onmousemove = function() {
            console.log('我是onmousemove');
        };
    </script>
</body>
</html>

2.常见的键盘事件监听

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    姓名:
    <input type="text" id="nameField">

    <script>
        var nameField = document.getElementById('nameField');

        nameField.onkeydown = function () {
            console.log('我是onkeydown');
        };

        nameField.onkeypress = function() {
            console.log('我是onkeypress');
        }

        nameField.onkeyup = function() {
            console.log('我是onkeyup');
        }
    </script>
</body>
</html>

3.事件传播

事件传播是:先从外到内,再从内到外。

(1)onxxx写法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box1{
            width: 202px;
            height: 202px;
            border: 1px solid #000;
            padding: 50px;
        }
        #box2{
            width: 100px;
            height: 100px;
            border: 1px solid #000;
            padding: 50px;
        }
        #box3{
            width: 100px;
            height: 100px;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
    <script>
        var oBox1 = document.getElementById('box1');
        var oBox2 = document.getElementById('box2');
        var oBox3 = document.getElementById('box3');

        oBox2.onclick = function () {
            console.log('我是box2的onclick');
        };

        oBox3.onclick = function () {
            console.log('我是box3的onclick');
        };

        oBox1.onclick = function () {
            console.log('我是box1的onclick');
        };
    </script>
</body>
</html>
(2) addEventListener()方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box1{
            width: 202px;
            height: 202px;
            border: 1px solid #000;
            padding: 50px;
        }
        #box2{
            width: 100px;
            height: 100px;
            border: 1px solid #000;
            padding: 50px;
        }
        #box3{
            width: 100px;
            height: 100px;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
    <script>
        var oBox1 = document.getElementById('box1');
        var oBox2 = document.getElementById('box2');
        var oBox3 = document.getElementById('box3');

      

        oBox2.addEventListener('click', function() {
            console.log('我是box2的冒泡阶段');
        }, false);
      
      
        oBox3.addEventListener('click', function() {
            console.log('我是box3的捕获阶段');
        }, true);

        oBox3.addEventListener('click', function() {
            console.log('我是box3的冒泡阶段');
        }, false);

        oBox3.onclick = function () {
            console.log('我是box3的onclick');
        };

        oBox1.addEventListener('click', function() {
            console.log('我是box1的冒泡阶段');
        }, false);

        oBox2.addEventListener('click', function() {
            console.log('我是box2的捕获阶段');
        }, true);

        oBox1.addEventListener('click', function() {
            console.log('我是box1的捕获阶段');
        }, true);

        oBox1.onclick = function () {
            console.log('我是box1的onclick');
        };

        oBox2.onclick = function () {
            console.log('我是box2的onclick');
        };

     
    </script>
</body>
</html>

4.事件对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        #box{
            width: 200px;
            height: 200px;
            background-color: #333;
            margin: 100px;
        }
        body{
            height: 2000px;
        }
        #info{
            font-size: 30px;
        }
         
    </style>
</head>
<body>
    <div id="box">
         
    </div>
    <div id="info"></div>

    <script>
        var oBox = document.getElementById('box');
        var oInfo = document.getElementById('info');

        oBox.onmousemove = function (e) {
            oInfo.innerHTML = 'offsetX/Y:' + e.offsetX + ',' + e.offsetY + '<br>'
                            + 'clientX/Y:' + e.clientX + ',' + e.clientY + '<br>'
                            + 'pageX/Y:' + e.pageX + ',' + e.pageY;
        };
    </script>
</body>
</html>

5.charCode和keyCode

demo:按键使盒子移动

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box {
            position: absolute;
            top: 200px;
            left: 200px;
            width: 100px;
            height: 100px;
            background-color: orange;
        }
    </style>
</head>

<body>
    <div id="box"></div>

    <script>
        var oBox = document.getElementById('box');

        // 全局变量t、l,分别表示盒子的top属性值和left属性值
        var t = 200;
        var l = 200;

        // 监听document对象的键盘按下事件监听,表示当用户在整个网页上按下按键的时候
        document.onkeydown = function (e) {
            switch (e.keyCode) {
                case 37:
                    l -= 3;
                    break;
                case 38:
                    t -= 3;
                    break;
                case 39:
                    l += 3;
                    break;
                case 40:
                    t += 3;
                    break;
            }

            // 更改样式
            oBox.style.left = l + 'px';
            oBox.style.top = t + 'px';
        };
    </script>
</body>

</html>

 6.e.preventDefault()方法

Demo1:阻止文本框的默认行为(默认是敲一个字母就会在文本框里显示,现在阻止这种行为)

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <p>
        只能输入小写字母和数字:
        <input type="text" id="field">
    </p>
    <script>
        var oField = document.getElementById('field');

        oField.onkeypress = function (e) {
            console.log(e.charCode);
            
            // 根据用户输入的字符的字符码(e.charCode)
            // 数字0~9,字符码48~57
            // 小写字母a~z,字符码97~122
            if (!(e.charCode >= 48 && e.charCode <= 57 || e.charCode >= 97 && e.charCode <= 122)) {
                // 阻止浏览器的默认行为
                e.preventDefault();
            }
        };
    </script>
</body>

</html>

 Demo2:制作鼠标滚轮事件:当鼠标在盒子中向下滚动时,数字+1;反之,数字-1。

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box {
            width: 200px;
            height: 200px;
            background-color: #333;
        }
        body{
            height: 2000px;
        }
    </style>
</head>

<body>
    <div id="box"></div>
    <h1 id="info">0</h1>

    <script>
        var oBox = document.getElementById('box');
        var oInfo = document.getElementById('info');

        // 全局变量就是info中显示的数字
        var a = 0;

        // 给box盒子添加鼠标滚轮事件监听
        oBox.onmousewheel = function (e) {
            // 阻止默认事件:就是说当用户在盒子里面滚动鼠标滚轮的时候,此时不会引发页面的滚动条的滚动
            e.preventDefault();
            
            if (e.deltaY > 0) {
                a++;
            } else {
                a--;
            }
            oInfo.innerText = a;
        }
    </script>
</body>

</html>

 7.stopPropagation()方法

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: #333;
        }
    </style>
</head>

<body>
    <div id="box">
        <button id="btn">按我</button>
    </div>
    <script>
        var oBox = document.getElementById('box');
        var oBtn = document.getElementById('btn');

        // oBox.onclick = function () {
        //     console.log('我是盒子');
        // };

        // oBtn.onclick = function (e) {
        //     阻止事件继续传播
        //     e.stopPropagation();
        //     console.log('我是按钮');
        // };

        oBox.addEventListener('click', function(e) {
            // 阻止事件继续传播
            e.stopPropagation();
            console.log('我是盒子');
        }, true)//true代表捕获阶段

        oBtn.addEventListener('click', function() {
            console.log('我是按钮');
        }, true);
    </script>
</body>

</html>

 

Demo:制造弹出层

制作一个弹出层,点击按钮显示弹出层,点击网页除它自身外的任意地方,弹出层关闭。

如果不去阻止事件传播,会点击按钮的瞬间就关闭,因为按钮也是网页的任意地方。

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .modal {
            width: 400px;
            height: 140px;
            background-color: #333;
            position: absolute;
            top: 50%;
            left: 50%;
            margin-top: -70px;
            margin-left: -200px;
            display: none;
        }
    </style>
</head>

<body>
    <button id="btn">按我弹出弹出层</button>
    <div class="modal" id="modal"></div>

    <script>
        var oBtn = document.getElementById('btn');
        var oModal = document.getElementById('modal');

        // 点击按钮的时候,弹出层显示
        oBtn.onclick = function (e) {
            // 阻止事件继续传播到document身上
            e.stopPropagation();
            oModal.style.display = 'block';
        };

        // 点击页面任何部分的时候,弹出层关闭
        document.onclick = function () {
            oModal.style.display = 'none';
        };

        // 点击弹出层内部的时候,不能关闭弹出层的,所以应该阻止事件继续传播
        oModal.onclick = function (e) {
            // 阻止事件继续传播到document身上
            e.stopPropagation();
        };
    </script>
</body>

</html>

8.事件委托

Demo1:批量添加点击事件监听

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <ul id="list">
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
    </ul>

    <script>
        var oList = document.getElementById('list');
        var lis = oList.getElementsByTagName('li');

        // 书写循环语句,批量给元素添加监听
        for (var i = 0; i < lis.length; i++) {
            lis[i].onclick = function () {
                // 在这个函数中,this表示点击的这个元素,this涉及函数上下文的相关知识,我们在“面向对象”课程中介绍
                this.style.color = 'red';
            };
        }
    </script>
</body>

</html>

 

 Demo2:新增元素动态绑定事件

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button id="btn">按我添加新的li列表项</button>
    <ul id="list"></ul>

    <script>
        var oBtn = document.getElementById('btn');
        var oList = document.getElementById('list');
        var lis = oList.getElementsByTagName('li');

        // 按钮的点击事件
        oBtn.onclick = function () {
            // 创建一个新的li列表项,孤儿节点
            var oLi = document.createElement('li');
            oLi.innerHTML = '我是列表项';
            // 上树
            oList.appendChild(oLi);
            // 给新创建的这个li节点添加onclick事件监听
            oLi.onclick = function () {
                this.style.color = 'red';
            };
        };
    </script>
</body>

</html>

 

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button id="btn">按我创建一个新列表项</button>
    <ul id="list">
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
    </ul>
    <script>
        var oList = document.getElementById('list');
        var oBtn = document.getElementById('btn');

        oList.onclick = function (e) {
            // e.target表示用户真正点击的那个元素
            e.target.style.color = 'red';
        };

        oBtn.onclick = function () {
            // 创建新的li元素
            var oLi = document.createElement('li');
            // 写内容
            oLi.innerText = '我是新来的';
            // 上树
            oList.appendChild(oLi);
        };
    </script>
</body>

</html>

 

demo3:注意事件是不是冒泡

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button id="btn">按我创建一个新列表项</button>
    <ul id="list">
        <li>列表项</li>
        <li>列表项</li>
        <li>列表项</li>
    </ul>
    <script>
        var oList = document.getElementById('list');
        var oBtn = document.getElementById('btn');

        // onmouseenter这个属性天生就是“不冒泡”的,相当于你事件处理函数附加给了哪个DOM节点
        // 就是哪个DOM节点自己触发的事件,没有冒泡过程
        oList.onmouseover = function (e) {
            // e.target表示用户真正点击的那个元素
            e.target.style.color = 'red';
        };

        oBtn.onclick = function () {
            // 创建新的li元素
            var oLi = document.createElement('li');
            // 写内容
            oLi.innerText = '我是新来的';
            // 上树
            oList.appendChild(oLi);
        };
    </script>
</body>

</html>

 

三、实现动画

;