你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

【JavaScript】学习第十四天(事件传播、阻止事件冒泡、事件委托)

2021/12/16 15:14:42

1.事件流(事件传播)

概念
描述页面接收事件的顺序,事件发生时,事件会在元素节点之间按照特定的顺序,依次传播。

思考
互相嵌套的div,同时给每个元素绑定了不同结果的相同事件,事件会如何传播

IE提出的是冒泡流
事件开始时由最具体的元素接收,然后逐级向上到DOM顶级节点

网景提出的是捕获流
事件开始时从DOM顶级节点开始,然后逐层向下传递到最具体的元素

W3C规范
js事件传播流程主要有三个阶段:

  • 事件捕获阶段:从window向 目标 传递的过程
  • 处于目标阶段:具体点击的是谁?事件发生在目标身上
  • 事件冒泡阶段:从目标向window传递的过程

DOM2可以支持捕获
事件源 . addEventListener(‘事件类型’,事件处理函数,布尔true事件捕获、false事件冒泡,不写就是默认冒泡)

DOM0级不支持捕获写法
现代的浏览器在默认情况下,都是事件冒泡模型。
如果想支持事件捕获,需要用DOM2级事件来设置

2.阻止事件冒泡

为什么要阻止

很多情况下我们并不希望事件冒泡的发生。
比如当我们想实现

  • 点击按钮,让元素显示;
  • 点击页面空白即(document)时让元素隐藏。

如何组止

  • IE浏览器:事件对象 . cancelBubble = true
  • 非IE浏览器阻止方式为:事件对象 . stopPropagation()
<!DOCTYPE html>
<html>

<head>
    <title></title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta name="viewport"
        content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
    <style>
        div {
            width: 200px;
            height: 200px;
            background-color: pink;
            display: none;
        }
    </style>
</head>

<body>
    <button>按钮</button>
    <div></div>
</body>

</html>
<script>
    var oDiv = document.querySelector('div')
    var oBtn = document.querySelector('button')
    oBtn.onclick = function (e) {
        var ev = e || window.event;
        oDiv.style.display = 'block'
        ev.stopPropagation();
        console.log(ev);
    }
    document.body.onclick = function () {
        oDiv.style.display = 'none'
    }
</script>

阻止事件默认行为:

什么是事件默认行为
没有绑定事件,自身具有的行为就是默认行为
比如:

1.a标签的点击行为
2.form表单的提交行为
3.鼠标右键时弹出菜单的行为
...

如何阻止

1.IE 低版本:事件对象 . returnValue = false
2.标准浏览器:事件对象 . preventDefault( )
3.在事件代码的最后加 return false (只支持DOM0级事件)

例子:

<!DOCTYPE html>
<html>

<head>
    <title></title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta name="viewport"
        content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
    <style>
        div {
            width: 200px;
            height: 200px;
            background-color: pink;
            display: none;
        }
    </style>
</head>

<body>
    <a href="http://www.baidu.com">百度</a>
    <div>

    </div>
</body>

</html>
<script>
    var oA = document.querySelector('a')
    var oDiv = document.querySelector('div')
    oA.onclick = function (e) {
        var ev = e || window.event;
        //    ev.preventDefault();//阻止事件默认行为方式
        oDiv.style.display = 'block'
        return false;//阻止事件默认行为方式2
    }
</script>

3.事件委托

出现原因:

  • 如果给每个 li 列表项都绑定一个onclick,每一个 li 身上都有一个onclick
  • 占用系统内存大,资源消耗大

概念:

即是把原本需要绑定在子元素的响应事件(click、keydown…)

事件委托的好处:

  • 把绑定事件委托父元素来处理(利用冒泡元素)
  • 可以大量节省内存占用,减少事件的绑定

例子:

<!DOCTYPE html>
<html>

<head>
    <title></title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8">
    <meta name="viewport"
        content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0" />
</head>

<body>
    <ul>
        <li>1个元素</li>
        <li>2个元素</li>
        <li>3个元素</li>
        <li>4个元素</li>
        <li>5个元素</li>
    </ul>
</body>

</html>
<script>
    /* 
      每一个添加点击事件:
      1. 先获取所有的li
      2. 遍历
      3. 给每一个添加点击事件
     */
    var oUl = document.querySelector('ul')

    oUl.onclick = function(e){
        var ev = e || window.event;
        // 通过ev.target来获取点击的具体元素
        // 点击元素是li的时候,执行获取内容
        if (ev.target.nodeName == 'LI') {
            console.log(ev.target.innerHTML);
        }
    }



</script>