zl程序教程

您现在的位置是:首页 >  前端

当前栏目

【学习笔记44】JavaScript的事件传播

2023-09-11 14:14:57 时间

一、事件传播

  • 在触发子元素的事件时, 会将行为传播给父级的同类型事件
  • 触发了子元素的点击事件时, 会将该行为传播给父级, 并触发父级的同类型事件
  • 在传递行为时, 会将行为一直向上传递, 如果父级有同类型事件, 那么触发该事件; 如果没有, 则继续往上传递
  • 阻止事件传播: e.stopPropagation()
        <div id="box1">
            <div id="box2"></div>
        </div>
        <style>
            #box1{
                width: 200px;
                height: 200px;
                background-color: cadetblue;
            }
            #box2{
                width: 100px;
                height: 100px;
                background-color: burlywood;
            }
        </style>

1、事件传播的说明

        // 获取标签对象
        var oBox1 = document.getElementById('box1');
        var oBox2 = document.getElementById('box2');
        var oBody = document.body;

        oBox1.onclick = function () {
            console.log('触发了box1的点击事件');
        }

        oBox2.onclick = function () {
            console.log('触发了box2的点击事件');
        }

        oBox1.oncontextmenu = function () {
            console.log('触发了box1的右键事件');
        }

        oBody.onclick = function () {
            console.log('触发了body的点击事件');
        }

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2、阻止事件传播

       // 获取标签对象
        var oBox1 = document.getElementById('box1');
        var oBox2 = document.getElementById('box2');
        var oBody = document.body;

        oBox1.onclick = function (e) {
            // 阻止事件传播
            e.stopPropagation() 
            console.log('触发了box1的点击事件');
        }

        oBox2.onclick = function () {
            console.log('触发了box2的点击事件');
        }

        oBox1.oncontextmenu = function () {
            console.log('触发了box1的右键事件');
        }

        oBody.onclick = function () {
            console.log('触发了body的点击事件');
        }

在这里插入图片描述

二、目标冒泡捕获

  • 目标: 目标就是事件源
  • 传播时,会从目标传播到父级, body, html, document, window
        <div id="box1">
            <div id="box2"></div>
        </div>
        <style>
            #box1{
                width: 200px;
                height: 200px;
                background-color: cadetblue;
            }
            #box2{
                width: 100px;
                height: 100px;
                background-color: burlywood;
            }
        </style>

1、冒泡

  • 冒泡: 事件传播时, 从目标开始传播, 一直到到父级, body...window
  • window 默认的传播方式为 冒泡
        // 获取标签对象
        var oBox1 = document.getElementById('box1');
        var oBox2 = document.getElementById('box2');
        var oBody = document.body;

        oBox1.onclick = function () {
            console.log('触发了box1的点击事件');
        }

        oBox2.onclick = function () {
            console.log('触发了box2的点击事件');
        }

        oBox1.oncontextmenu = function () {
            console.log('触发了box1的右键事件');
        }

        oBody.onclick = function () {
            console.log('触发了body的点击事件');
        }

在这里插入图片描述

2、捕获

  • 捕获: 从最顶层开始, 逐层向下传递, 一直到目标
        // 获取标签对象
        var oBox1 = document.getElementById('box1');
        var oBox2 = document.getElementById('box2');
        var oBody = document.body;

        // 捕获
        oBox1.addEventListener('click', function(){
            console.log('触发了box1的点击事件');
        }, true)

        oBox2.addEventListener('click', function(){
           console.log('触发了box2的点击事件');
        }, true)

        oBody.addEventListener('click', function(){
             console.log('触发了body的点击事件');
        }, true)

在这里插入图片描述

解释说明

  1. addEventListener第三个参数默认值为false,代表传播方式为冒泡
  2. 如果想改变传播方式为捕获, 那么需要将第三个参数传递为true

三、事件委托

  1. 因为事件冒泡的存在, 所以点击子元素时, 一定会触发给父级
  2. 所以可以将子元素统一的事件, 都提交给父级
  3. e.target: 触发事件的事件源
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
    <style>
        ul{
            list-style: none;
        }
        li{
            width: 200px;
            height: 100px;
            background-color: cornflowerblue;
            margin-bottom: 5px;
        }
    </style>

1、事件委托的说明

        // 获取标签对象
        var oUl = document.querySelector('ul');

        oUl.addEventListener('click', function(event){
            
            console.log(event.target.nodeName);
        })

在这里插入图片描述

        // 获取标签对象
        var oUl = document.querySelector('ul');

        oUl.addEventListener('click', function(event){
            // 判断
            if(event.target.nodeName === 'LI'){
                console.log('点击了li');
            }
        })

在这里插入图片描述

2、为什么要用事件委托

  1. 动态的添加了li时, 新加的li没有绑定上事件, 需要动态添加完成后重新绑定事件, 这样操作比较麻烦,所以此时可以利用事件委托
  2. li 的点击事件必须委托给父级点击事件
        // 获取标签对象
        var oUl = document.querySelector('ul');
        var oLi = [...document.querySelectorAll('li')];

        // 创建一个Li节点
        var newLi = document.createElement('li');
        newLi.innerText = '我是通过JS创建的';

        oUl.appendChild(newLi);

        // 此时页面只有3个li, 所以新插入的li没有点击事件
        oLi.forEach(function (item, index) {
            item.onclick = function () {
                console.log(index + 1)
            }
        })

在这里插入图片描述

在这里插入图片描述

四、阻止默认事件

    <!-- a标签默认是跳转页面 -->
    <a href="xxx">点击跳转</a>

1、方法一

  • return false; 阻止a标签跳转
        var oA = document.querySelector('a');
        oA.onclick = function (e) {
            return false
        }

2、方法二

  • preventDefault();拦截之后, 取消了a标签的默认跳转功能
        var oA = document.querySelector('a');
        oA.onclick = function (e) {  
            e.preventDefault()
        }