一幅长文细学JavaScript(三)——DOM

3 JavaScript DOM

在前面的JS基础阶段中,我们学习的是ECMAScript标准规定的基本语法,但是只学习基本语法是无法做出网页交互效果的,为此在本章的学习中,我们要进入WebAPIs阶段。

WebAPIs是W3C组织的标准,主要学习DOM和BOM,在这一章节中,我们需要JS基本语法的铺垫,步入学习网页交互功能的道路。


3.1 DOM基本术语

DOM模型及其作用

​ 当网页被加载时,浏览器会创建页面的文档对象模型(Document Object Model),它是W3C组织推荐的处理可扩展标记语言的标准编程接口,其结构为一颗DOM对象树。如果学过Python爬虫中的Xpath解析框架,你可以很好的理解我上述的话。

image-20220712223121800

​ Js可以通过DOM对HTML文档进行操作,即随心所欲操作Web界面。

  • JavaScript 能改变页面中的所有 HTML 元素
  • JavaScript 能改变页面中的所有 HTML 属性
  • JavaScript 能改变页面中的所有 CSS 样式
  • JavaScript 能删除已有的 HTML 元素和属性
  • JavaScript 能添加新的 HTML 元素和属性
  • JavaScript 能对页面中所有已有的 HTML 事件作出反应
  • JavaScript 能在页面中创建新的 HTML 事件

文档对象模型
  • 文档:一个HTML网页就是一个文档
  • 对象:网页中的每一个部分都转换为了一个对象
  • 模型:表示对象之间的关系,方便我们获取对象

节点

节点Node是构建网页最基本的组成部分。网页中的每一个部分都可看做是一个节点。节点类型多样,属性和方法也不尽相同,最常用的节点可以分为以下四类:

  • 文档节点:整个HTML文档;网页中所有的结点都是以子节点的形式存在,文档对象作为window对象的属性存在,我们不用获取可直接使用。通过该对象我们可以在整个文档访问内查找节点对象,并且可以通过该对象创建各种节点对象。
  • 元素节点:HTML文档中的HTML标签;我们可以通过多种方法访问到元素节点,如document.getElementById()。
  • 属性节点:元素的属性;通过元素节点.getAttributeNode(“属性名”)可以找到属性节点对象,但我们很少使用它。
  • 文本节点:HTML标签中的文本内容;使用元素节点.firstChild可以获取元素节点的文本节点,其一般为元素节点的第一个子节点。

节点的属性

对于每个节点来说都具备nodeName、nodeType、nodeValue三个属性。

nodeNamenodeTypenodeValue
文档节点#document9Null
元素节点标签名1Null
属性节点属性名2属性值
文本节点#text3文本内容

文档对象
  • 浏览器为我们提供了文档节点对象document,这个对象是window属性。如果你希望访问HTML页面中的任何元素,那么你必须从访问document对象开始。

  • 文档节点对象可以在页面中直接使用,文档节点代表的是整个网页


3.2 DOM文档操作

3.2.1 查找网页元素

方法说明
document.getElementById(‘id’)元素id查找元素
document.getElementByTagName(‘name’)标签名查找元素
document.getElementByClassName(‘name’)类名查找元素
document.querySelector(‘CSS选择器’)根据CSS选择器返回第一个元素
document.querySelectorAll(‘CSS选择器’)通过CSS选择器选择多个元素
document.body选择body标签的所有内容
document.documentElement选择html标签的所有内容

:JS是解释性语言,故JS代码必须写在HTML的下方,因为只有HTML生成元素了,JS才能通过DOM操纵元素。

<!DOCTYPE html>
<html lang="zh-cn">
<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>Document</title>
</head>
<body>
    <!-- HTML元素 -->
    <div id = "test">测试案例1</div>
    <p>测试案例2</p>
    <p>测试案例3</p>
    <div class="c1">测试案例4</div>
    <div class = "c2">测试案例5</div>
    <div id = "c3">测试案例6</div>
    <div id = "c3">测试案例7</div>
    
    <script>
        //1 通过ID找元素,注意ID大小写敏感,返回值为
        var test1 = document.getElementById('test');
        console.log(test1);
        console.dir(test1);//等同于log,用于查看元素结构
        
        //2 通过标签名找元素,这种方式选中所有同名标签,返回值为伪数组
        var test2 = document.getElementsByTagName('p');
        console.log(test2);

        //3 通过类名找元素,该方法仅支持IE9以上,返回值为伪数组
        var test3 = document.getElementsByClassName('c1');
        console.log(test3);
        
        //4 通过选择器查找第一个元素
        var test4 = document.querySelector('.c2');
        console.log(test4);
        
        //5 通过选择器选定所有元素
        var test5 = document.querySelectorAll('#c3');
        console.log(test5);
        var test6 = document.querySelectorAll('*');
        console.log(test6);
        
        //6 得到body元素
        var test7 = document.body;
        console.log(test7);

        //7 得到html元素
        var test8 = document.documentElement;
        console.log(test8);
    </script>
</body>
</html>

3.2.2 获取元素内容

:推荐学完事件再回来看

方法说明
元素节点.innerText获取HTML元素标签间的内容
元素节点.innerHTML获取HTML元素标签间内容以及标签
元素节点.属性获取HTML元素的属性值
元素节点.style.样式获取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>Document</title>
    <style>
        #Test5 p{
            height:50px;
            width:100px;
            background: pink;
        }
    </style>
</head>
<body>
    <!-- 测试组件 -->
    <button>测试按钮1</button>
    <div>测试内容1</div>
    <br>
    <div>
        <button id = "testbtn2">测试按钮2</button>
        <p id = "test2">测试内容2</p>
    </div>
    <br>
    <div>
        <button id = "testbtn3">测试按钮3——图片1</button>
        <button id = "testbtn4">测试按钮4——图片2</button>
        <br>
        <img src = "./img_103.jpg" alt = "" id = "testimg" width = 300px>
    </div>
    <div id = "Test5">
        <p>测试内容5</p>
        <br>
        <button>测试按钮5</button>
    </div>
    
    <script>
        /*======innerText======*/
        //1 获取事件源
        var btn1 = document.querySelector('button');
        var div1 = document.querySelector('div');

        //2 注册事件
        btn1.onclick = function(){
            div1.innerText = '测试内容已改变';
        }
        
        /*======innerHTML======*/
        //1 获取事件源
        var btn2 = document.getElementById('testbtn2')
        var p2 = document.getElementById('test2');
        //2 注册事件
        btn2.onclick = function(){
            p2.innerHTML = '<strong>测试内容已改变</strong>';
        }

        /*======元素节点.属性======*/
        //1 获取事件源
        var btn3 = document.getElementById('testbtn3');
        var btn4 = document.getElementById('testbtn4');
        var img3  = document.getElementById('testimg');
        //2 注册事件
        btn3.onclick = function(){
            img3.src = './img_103.jpg';
        }
        btn4.onclick = function(){
            img3.src = './img_112.jpg';
        }

        /*======元素节点.style.样式======*/
        //1 获取事件源
        var btn5 = document.querySelector('#Test5 button');
        var p5 = document.querySelector('#Test5 p');
        //2 注册事件
        btn5.onclick = function(){
            p5.style.background = 'skyblue';
        }
    </script>
</body>
</html>

新的策略——修改样式

说明:如果要想通过DOM修改CSS样式,一个样式就要一条语句,十分难受。为此,我们可以将修改后的样式放在一个选择器中,当我们需要很多组件同时变成该样式时,使用元素.className修改该元素的所属的类,这样就可以给该元素附上提前准备好的样式。

:className方法并不是添加类,而是覆盖类。这就意味着如果元素此前拥有的类将会被覆盖。

<!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>Document</title>
    <style>
        /*提前准备一个样式*/
        .Test1{
            color: yellowgreen;
            background: pink;
        }
    </style>
</head>
<body>
    <div>测试内容1</div>
    <button>测试按钮1</button>
    <script>
        var div1 = document.querySelector('div');
        var btn1 = document.querySelector('button');
        btn1.onclick = function(){
            div1.className = 'Test1';
        }
    </script>
</body>
</html>

更好的策略——修改样式

说明:之前的className容易覆盖以前的类名,故我们可以使用classList方式来追加和删除类名。

方式说明
元素.classList.add(‘类名’)追加一个类
元素.classList.remove(‘类名’)删除一个类
元素.classList.toggle(‘类名’)切换一个类
<!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>Document</title>
    <style>
        /*提前准备一个样式*/
        .Test1{
            color: yellowgreen;
            background: pink;
        }

        /*样式2*/
        .Test2{
            background-color: aqua;
        }
    </style>
</head>
<body>
    <div class = "Test1">测试内容1</div>
    <button class = "add-btn">追加样式类</button>
    <button class = "remove-btn">删除样式类</button>
    <button class = "toggle-btn">切换样式类</button>
    <script>
        var div = document.querySelector('div')
        var add_btn = document.querySelector('.add-btn')
        var remove_btn = document.querySelector('.remove-btn')
        var toggle_btn = document.querySelector('.toggle-btn')
        console.log(add_btn);
        console.log(remove_btn);
        add_btn.onclick = function(){
            div.classList.add('Test2')
        }

        remove_btn.onclick = function(){
            div.classList.remove('Test2');
        }

        toggle_btn.onclick = function(){
            div.classList.toggle('Test1');
        }
    </script>
</body>
</html>

3.2.3 改变元素内容

说明:我们可以通过以下方法修改元素的内容

方法说明
元素节点.innerText =新内容改变元素的标签值
元素节点.innerHTML = 新元素改变元素
元素节点.属性 = 新的属性值改变元素的属性值
元素节点.setAttribute(属性, 值)改变元素的属性值
元素节点.style.样式 = 新的属性值改变 HTML 元素的行内样式值

3.2.4 操作网页元素

创建 HTML 元素节点:document.createElement(element)

创建 HTML 属性节点:document.createAttribute(attribute)

创建 HTML 文本节点:document.createTextNode(text)

删除 HTML 元素:元素节点.removeChild(element)

添加 HTML 元素:元素节点.appendChild(element)

替换 HTML 元素:元素节点.replaceChild(element)

在指定的子节点前面插入新的子节点:元素节点.insertBefore(element)


3.2.5 获取元素偏移

说明:offset指偏移量,我们使用offset系列相关属性可以动态地获取该元素的位置、大小等。需要注意的是,获取的仅有数值而无单位

方法说明
元素.offsetWidth返回自身包括padding、边框、内容区的宽度,返回数值不带单位
元素.offsetHeight返回自身包括padding、边框、内容区的高度,返回数值不带单位
元素.offsetParent获取离当前元素最近的开启了定位的祖先元素
元素.offsetTop返回元素相对带有定位父元素上方的偏移
元素.offsetLeft返回元素相对带有定位父元素左边框的偏移
<!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>Document</title>
    <style>
        *{
            margin:0;
            padding:0;
        }
        .div{
            background-color: pink;
            height: 200px;
            width: 200px;
            border: 2px solid red;
            padding:2px;
        }
    </style>
</head>
<body>
    <div class = "div"></div>
    <script>
        var div = document.querySelector(".div")
        // offsetWidth返回自身包括padding、边框、内容区的宽度,返回数值不带单位
        console.log(div.offsetWidth);
        // offsetHeight返回自身包括padding、边框、内容区的高度,返回数值不带单位
        console.log(div.offsetHeight);
        // offsetParent获取离当前元素最近的开启了定位的祖先元素
        console.log(div.offsetParent);
        // offsetTop返回元素相对带有定位父元素上方的偏移
        console.log(div.offsetTop);
        // offsetLeft返回元素相对带有定位父元素左边框的偏移
        console.log(div.offsetLeft);
    </script>
</body>
</html>

offset和style的区别
offsetstyle
offset可以得到任意样式表中的样式值style只能得到行内样式表中的样式值
offset系列获得的数值是不带单位的style.width获得的是带有单位的字符串
offsetWidth包含padding+border+widthstyle.width获得不包含padding和border的值
offsetWidth等属性属于只读属性style.widh是可读写属性,可以获取也可以赋值

3.2.6 获取元素可视区

方法说明
元素.clientWidth返回自身包括padding、内容区宽度、不含边框,返回数值不带单位
元素.clientHeight返回自身包括padding、内容区高度、不含边框,返回数值不带单位
元素.clientTop返回元素上边框的大小
元素.cllientLeft返回元素左边框的大小
<!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>Document</title>
    <style>
        div{
            width: 200px;
            height: 200px;
            background-color: pink;
            border: 3px solid skyblue;
            margin: 0 auto;
        }
    </style>
</head>
<body>
    <div></div>

    <script>
        var div = document.querySelector('div');
        console.log(div.clientWidth); //200,说明不包含边框
        console.log(div.clientHeight);//200 说明不包含边框
        console.log(div.clientLeft);//3 边框的左边宽度为3
        console.log(div.clientTop);//3 边框的顶部宽度为3
    </script>
</body>
</html>

3.2.7 获取元素滚动

方法说明
元素.scrollTop返回被卷去的上侧距离,返回数值不带单位
元素.scrollLeft返回被卷去的左侧距离,返回数值不带单位
元素.scrollWidth返回自身实际的宽度,不含边框,返回数值不带单位
元素.scrollHeight返回自身实际的高度,不含边框,返回数值不带单位

image-20220723112541620

<!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>Document</title>
    <style>
        div{
            width:50px;
            height:100px;
            background-color: pink;
            overflow: scroll;
            border: 3px solid red;
        }
    </style>
</head>
<body>
    <div>测试内容1  测试内容1  测试内容1  测试内容1  </div>
    <script>
        var div = document.querySelector('div');
        console.log(div.scrollHeight);//208 表名内容+padding的宽度为208
        console.log(div.scrollTop); //0 表明没有内容在滚动条上面
        console.log(div.scrollWidth);//33 表名内容+padding的宽度为33
        console.log(div.scrollLeft);//0表名没有内容在滚动条左侧
    </script>
</body>
</html>

3.2.8 元素节点导航

说明:在前面的选择器中,我们通通都是使用DOM提供的方法来获取元素,但这些方法逻辑性不强且繁琐。为此,Js还提供了利用节点层级来获取元素。

方法描述
元素节点.parentNode返回元素的父节点。
元素节点.parentElement返回元素的父元素。
元素节点.childNodes返回元素的一个子节点的数组(包含空白文本Text节点)。
元素节点.children返回元素的一个子元素的集合(不包含空白文本Text节点)。但其为非标准方法
元素节点.firstChild返回元素的第一个子节点(包含空白文本Text节点)。
元素节点.firstElementChild返回元素的第一个子元素(不包含空白文本Text节点)。
元素节点.lastChild返回元素的最后一个子节点(包含空白文本Text节点)。
元素节点.lastElementChild返回元素的最后一个子元素(不包含空白文本Text节点)。
元素节点.previousSibling返回某个元素紧接之前节点(包含空白文本Text节点)。
元素节点.previousElementSibling返回指定元素的前一个兄弟元素(相同节点树层中的前一个元素节点)。
元素节点.nextSibling返回某个元素紧接之后节点(包含空白文本Text节点)。
元素节点.nextElementSibling返回指定元素的后一个兄弟元素(相同节点树层中的下一个元素节点)。
<div>我是div</div>
    <span>我是span</span>
    <ul>
        <li>我是li</li>
        <li>我是li</li>
        <li>我是li</li>
    </ul>
    <div class="box">
        <span class = "erweima">×</span>
    </div>
    <script>
        // 1.通过已知元素节点获取最近的父节点
        var erweima = document.querySelector('.erweima')
        // var box = document.querySelector('.box') 传统写法
        var box = erweima.parentNode //元素导航写法
        console.log(box);
        
        // 2.通过已知元素节点获取所有的子节点,子节点中既有元素节点也有文本节点
        // 通常不建议使用该方法来获取子节点,因为太麻烦了
        var ul = document.querySelector('ul')
        console.log(ul.childNodes);

        // 3.非标准方法,但其获得所有浏览器认可,用于选取已知元素节点的所有子元素节点
        console.log(ul.children);

        // 4.获取第一个子节点
        console.log(ul.firstChild);

        // 5.获取第一个元素子节点
        console.log(ul.firstElementChild);

        // 6.获取最后一个子节点
        console.log(ul.lastChild);

        // 7.获取最后一个元素子节点
        console.log(ul.lastElementChild);
    </script>

3.2.9 查找网页元素

属性说明
document.anchors返回拥有 name 属性的所有<a> 元素
document.baseURI返回文档的绝对基准 URI
document.body返回 <body> 元素
document.cookie返回文档的 cookie
document.doctype返回文档的 doctype
document.documentElement返回 <html> 元素
document.documentMode返回浏览器使用的模式
document.documentURI返回文档的 URI
document.domain返回文档服务器的域名
document.forms返回所有 <form> 元素
document.embeds返回所有 <embed> 元素
document.images返回所有 <img> 元素
document.lastModified返回文档更新的日期和时间
document.title返回 <title> 元素
document.scripts返回所有 <script> 元素

3.3 DOM文档事件

3.3.1 事件入门

事件基本概念

事件:编程时系统内发生的动作或者发生的事情

事件监听:让程序检测是否有事件发生,一旦有事件触发,就立即调用一个函数做出响应,也称为注册事件。


事件的三要素
  • 事件源:事件被触发的对象
  • 事件类型:如何触发
  • 事件调用的函数:要做什么事

执行事件的过程
  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序

3.3.2 事件绑定

事件监听版本
版本写法
DOM L0事件源.on事件 = function(){}
DOM L2事件源.addEventListener(事件,事件处理函数,布尔值)

  • L0和L2有很大区别,我们会在后面讨论。
  • 第三个参数时布尔值,指定使用事件冒泡还是事件捕获,如果是true则为捕获,如果是false则为传播,此参数可省略。
  • 在IE9之前不支持L2,可使用attachEvent()代替。

IE9之前的事件绑定

格式:事件源.attachEvent(事件,事件处理函数)

说明:官方在文档中明确指出,在实际开发中不要使用该方式


事件监听发展史
  • DMO L0:是DOM发展的第一个版本
  • DOM L1:1998.10.1称为W3C推荐标准
  • DOM L2:使用addEventListener注册事件
  • DOM L3:DOM3级别事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件类型
<!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>Document</title>
</head>
<body>
    <button id = "btn1">测试按钮1</button>
    <button id = "btn2">测试按钮2</button>

    <script>
        /*老版写法*/
        var btn1 = document.getElementById("btn1");
        btn1.onclick = function(){
            alert('按钮1已被点击');
        }


        /*新版写法*/
        var btn2 = document.getElementById("btn2");

        btn2.addEventListener("click", function(){
            alert('按钮2已被点击');
        })
    </script>
</body>
</html>

3.3.3 窗口事件

:在下面各类型事件的使用中,我们不推荐一个一个全部死记,要用什么查什么即可。

属性描述
onblur当窗口失去焦点时运行脚本。
onfocus当窗口获得焦点时运行脚本。
onload当文档加载之后运行脚本。
onresize当调整窗口大小时运行脚本。常用作响应式布局。
onstorage当 Web Storage 区域更新时(存储空间中的数据发生变化时)运行脚本。
DOMContentLoaded不包括样式表、图片、flash等,仅当DOM加载完成即触发时间,适合用于页面图片较多的情况

3.3.4 鼠标事件

属性描述
onclick当单击鼠标时运行脚本。
ondblclick当双击鼠标时运行脚本。
onmousedown当按下鼠标按钮时运行脚本。
onmouseup当松开鼠标按钮时运行脚本。
onmousemove当鼠标指针移动时运行脚本。
onmouseover当鼠标指针移至元素之上时运行脚本,不可以阻止冒泡。
onmouseout当鼠标指针移出元素时运行脚本,不可以阻止冒泡。
onmouseenter当鼠标指针移至元素之上时运行脚本,可以阻止冒泡。
onmouseleave当鼠标指针移出元素时运行脚本,可以阻止冒泡。
onmousewheel当转动鼠标滚轮时运行脚本。
onscroll当滚动元素的滚动条时运行脚本。

3.3.5 键盘事件

属性描述
onkeydown当按下按键时运行脚本。
onkeyup当松开按键时运行脚本。
onkeypress当按下并松开按键时运行脚本。

3.3.6 焦点事件

属性描述
focus获得焦点
blur失去焦点

3.3.7 文本事件

属性描述
input用户输入文本时开始运行脚本

3.3.8 表单事件

属性描述
onblur当元素失去焦点时运行脚本。
onfocus当元素获得焦点时运行脚本。
onchange当元素改变时运行脚本。
oninput当元素获得用户输入时运行脚本。
oninvalid当元素无效时运行脚本。
onselect当选取元素时运行脚本。
onsubmit当提交表单时运行脚本。

3.3.9 媒体事件

属性描述
onabort当发生中止事件时运行脚本。
oncanplay当媒介能够开始播放但可能因缓冲而需要停止时运行脚本。
oncanplaythrough当媒介能够无需因缓冲而停止即可播放至结尾时运行脚本。
ondurationchange当媒介长度改变时运行脚本。
onemptied当媒介资源元素突然为空时(网络错误、加载错误等)运行脚本。
onended当媒介已抵达结尾时运行脚本。
onerror当在元素加载期间发生错误时运行脚本。
onloadeddata当加载媒介数据时运行脚本。
onloadedmetadata当媒介元素的持续时间以及其它媒介数据已加载时运行脚本。
onloadstart当浏览器开始加载媒介数据时运行脚本。
onpause当媒介数据暂停时运行脚本。
onplay当媒介数据将要开始播放时运行脚本。
onplaying当媒介数据已开始播放时运行脚本。
onprogress当浏览器正在取媒介数据时运行脚本。
onratechange当媒介数据的播放速率改变时运行脚本。
onreadystatechange当就绪状态(ready-state)改变时运行脚本。
onseeked当媒介元素的定位属性不再为真且定位已结束时运行脚本。
onseeking当媒介元素的定位属性为真且定位已开始时运行脚本。
onstalled当取回媒介数据过程中(延迟)存在错误时运行脚本。
onsuspend当浏览器已在取媒介数据但在取回整个媒介文件之前停止时运行脚本。
ontimeupdate当媒介改变其播放位置时运行脚本。
onvolumechange当媒介改变音量亦或当音量被设置为静音时运行脚本。
onwaiting当媒介已停止播放但打算继续播放时运行脚本。

3.3.10 排他思想

排他思想:当前元素为A状态,其他为B状态

应用:轮播图等

<!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>Document</title>
    <style>
        .pink{
            background-color: pink;
        }
    </style>
</head>
<body>
    <button class = 'pink'>测试按钮1</button>
    <button>测试按钮2</button>
    <button>测试按钮3</button>

    <script>
        var btns = document.querySelectorAll('button');
        for (var i = 0; i < btns.length; i++) {
            btns[i].addEventListener('click',function(){
                document.querySelector('.pink').classList.remove('pink');
                this.classList.add('pink');
            })
        }
    </script>
</body>
</html>

3.3.11 事件冒泡

事件冒泡:事件的向上传导。当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发。

<!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>Document</title>
    <style>
        div{
            background: skyblue;
            width: 300px;
            height: 300px;
        }
        
        div  div{
            background: pink;
            height: 50px;
            width:50px;
        }
    </style>
</head>
<body>
    <div>
        <div></div>
    </div>

    <script>
        var innerDiv = document.querySelector('div > div');
        var outerDiv = document.querySelector('div');

        innerDiv.onclick = function(){
            alert("您点击了内层");
        }

        outerDiv.onclick = function(){
            alert("您点击了外层");
        }
    </script>
</body>
</html>

3.3.12 事件委派

事件委派:为多个元素绑定同一个事件。

事件委派原理:利用事件冒泡。将事件统一绑定给祖先元素后,点击后代元素,则后代元素会冒泡到祖先元素上去寻找事件。

事件委派的好处:通过委派可以减少事件绑定的次数,提高程序的性能。

<!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>Document</title>
    <style>
        p{
            background-color: greenyellow;
        }
    </style>
</head>
<body>
    <div class = "divClass">
        <p>测试内容1</p>
        <p>测试内容2</p>
        <p>测试内容3</p>
    </div>

    <script>
        var div1 = document.querySelector('div');
        /*target属性用于返回一个事件触发对象*/
        div1.onclick = function(event){
            if(event.target.className != 'divClass'){
                alert('测试内容已被点击');
            }
        }
    </script>
</body>
</html>

3.3.13 事件传播

事件流

说明:事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。如我们给一个div注册点击事件:

image-20220815234456616

这时候我们需要先去寻找这个元素,这个过程我们称为捕获阶段,找到当前目标后,进入当前目标阶段,对目标进行事件的执行,最后进入冒泡阶段,div元素执行事件后,父级元素如果有相同类型的事件,则也会触发,如两者都具有点击事件。

事件捕获

在HTML DOM中有两种事件传播方式:冒泡捕获。我们在前面已经谈论过冒泡,冒泡就是从内而外发生事件,而捕获则和冒泡反着来。


回到事件绑定
方法说明
事件源.addEventListener(事件,事件处理函数,布尔值)绑定事件
事件源.removeEventListener(事件,事件处理函数)解绑事件

  • L2绑定事件允许向相同元素添加多个不同类型的事件,且不覆盖
  • L2绑定和解绑只支持IE8之后的版本

3.3.14 事件对象

事件对象简介

说明:只要绑定了事件,则系统会自动创建一个事件对象event,可简写为e或evt。我们将其写于事件回调函数的参数列表中。


事件对象常用属性和方法
事件对象属性方法说明
e.target返回触发事件的对象
e.srcElement返回触发事件的对象 ie6-8才可使用
e.type返回事件的类型
e.cancelBubble阻止事件冒泡 ie6-8使用
e.returnValue阻止默认事件发生 ie6-8使用
e.preventDefault()阻止默认事件发生
e.stopPropagation()阻止事件冒泡
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ArimaMisaki

如果知识有用请我喝杯咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值