javaScript事件(一)事件流

一、事件

事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字。
事件是javaScript和DOM之间的桥梁。
你若触发,我便执行——事件发生,调用它的处理函数执行相应的JavaScript代码给出响应。
典型的例子有:页面加载完毕触发load事件;用户单击元素,触发click事件。

二、事件流

1、事件流感性认识
问题:单击页面元素,什么样的元素能感应到这样一个事件?
答案:单击元素的同时,也单击了元素的容器元素,甚至整个页面。
例子:有三个同心圆, 给每个圆添加对应的事件处理函数,弹出对应的文字。单击最里面的圆,同时也单击了外面的圆,所以外面圆的click事件也会被触发。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<style>
    #outer{
        position: absolute;
        width: 400px;
        height: 400px;
        top:0;
        left: 0;
        bottom:0;
        right: 0;
        margin: auto;
        background-color: deeppink;
    }
    #middle{
        position: absolute;
        width: 300px;
        height:300px;
        top:50%;
        left: 50%;
        margin-left: -150px;
        margin-top: -150px;
        background-color: deepskyblue;
    }
    #inner{
        position: absolute;
        width: 100px;
        height:100px;
        top:50%;
        left:50%;
        margin-left: -50px;
        margin-top: -50px;;
        background-color: darkgreen;
        text-align: center;
        line-height: 100px;
        color:white;
    }
    #outer,#middle,#inner{
border-radius:100%;
    }
</style>
<body>
<div id="outer">
   <div id="middle">
        <div id="inner">
            click me!
        </div>
    </div>
</div>
<script>
       var innerCircle= document.getElementById("inner");
        innerCircle.onclick= function () {
            alert("innerCircle");
        };
        var middleCircle= document.getElementById("middle");
        middleCircle.onclick=function(){
            alert("middleCircle");
        }
        var outerCircle= document.getElementById("outer");
        outerCircle.onclick= function () {
            alert("outerCircle");
        }
</script>
</body>
</html>

2、事件流

事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。
事件传播的顺序对应浏览器的两种事件流模型:捕获型事件流和冒泡型事件流。
冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。即从DOM树的叶子到根。
捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。即从DOM树的根到叶子。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<div id="myDiv">Click me!</div>
</body>
</html>

上面这段html代码中,单击了页面中的<div>元素,
在冒泡型事件流中click事件传播顺序为<div> —> <body>—> <html>—> document
在捕获型事件流中click事件传播顺序为document —> <html> —><body> —> <div>

<!DOCTYPE html>
<html>

<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<style>
#outer {
    position: absolute;
    width: 400px;
    height: 400px;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    margin: auto;
    background-color: deeppink;
}

#middle {
    position: absolute;
    width: 300px;
    height: 300px;
    top: 50%;
    left: 50%;
    margin-left: -150px;
    margin-top: -150px;
    background-color: deepskyblue;
}

#inner {
    position: absolute;
    width: 100px;
    height: 100px;
    top: 50%;
    left: 50%;
    margin-left: -50px;
    margin-top: -50px;
    ;
    background-color: darkgreen;
    text-align: center;
    line-height: 100px;
    color: white;
}

#outer,
#middle,
#inner {
    border-radius: 100%;
}
</style>

<body>
    <div id="outer">
        <div id="middle">
            <div id="inner">
                click me!
            </div>
        </div>
    </div>
    <script>
    //true - 事件句柄在捕获阶段执行
    //false- 事件句柄在冒泡阶段执行(默认)
    var innerCircle = document.getElementById("inner");
    innerCircle.addEventListener("click", function() {
        alert("innerCircle的click事件在捕获阶段被触发");
    }, true);
    innerCircle.addEventListener("click", function() {
        alert("innerCircle的click事件在冒泡阶段被触发");
    }, false);
    var middleCircle = document.getElementById("middle");
    middleCircle.addEventListener("click", function() {
        alert("middleCircle的click事件在捕获阶段被触发");
    }, true);
    middleCircle.addEventListener("click", function() {
        alert("middleCircle的click事件在冒泡阶段被触发");
    }, false);
    var outerCircle = document.getElementById("outer");
    outerCircle.addEventListener("click", function() {
        alert("outerCircle的click事件在捕获阶段被触发");
    }, true);
    outerCircle.addEventListener("click", function() {
        alert("outerCircle的click事件在冒泡阶段被触发");
    }, false);
    </script>
</body>

</html>

3、事件流的典型应用——事件代理

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

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>

    <body>
        <ul id="color-list">
            <li>red</li>
            <li>orange</li>
            <li>yellow</li>
            <li>green</li>
            <li>blue</li>
            <li>indigo</li>
            <li>purple</li>
        </ul>
        <script>
        (function() {
            var colorList = document.getElementById("color-list");
            colorList.addEventListener('click', showColor, false);

            function showColor(e) {
                e = e || window.event;
                var targetElement = e.target || e.srcElement;
                console.log(targetElement.nodeName.toLowerCase());
                if (targetElement.nodeName.toLowerCase() === "li") {
                    alert(targetElement.innerHTML);
                }
            }
        })();
        </script>
    </body>
</body>

</html>

a、将多个事件处理器减少到一个,因为事件处理器要驻留内存,这样就提高了性能。想象如果有一个100行的表格,对比传统的为每个单元格绑定事件处理器的方式和事件代理(即table上添加一个事件处理器),不难得出结论,事件代理确实避免了一些潜在的风险,提高了性能。

b、DOM更新无需重新绑定事件处理器,因为事件代理对不同子元素可采用不同处理方法。如果新增其他子元素(a,span,div等),直接修改事件代理的事件处理函数即可,不需要重新绑定处理器,不需要再次循环遍历。

原文地址:https://www.cnblogs.com/lgxlsm/p/6211932.html