玫瑰不香

导航

JavaScript - 事件

参考:https://www.cnblogs.com/st-leslie/p/5907556.html

   https://segmentfault.com/a/1190000013265547?utm_source=tag-newest#articleHeader0

事件

  HTML与JavaScript交互是通过事件驱动来实现的,例如鼠标点击事件、页面的滚动事件onscroll等等,可以向文档或者文档中的元素添加事件侦听器来预订事件。

1、事件流

事件流,事件触发的顺序。

IE提出冒泡流,网景提出捕获流。

JS事件流原理图:

  事件流过程:  捕获过程(1~5) -> 目标过程(5~6) -> 冒泡过程(6~7);

始于window,终于window的过程。

  事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。

  事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。

  事件冒泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。

(1)冒泡流

特征:自底向上

(2)捕获流

特征:自顶而下

2、事件级别

DOM级别与DOM事件关系图:

 

事件级别支持情况:

(1)DOM0 (HTML事件)

它是写在html里面的,是全局作用域:

例:

<div onclick="alert('1')"></div>

(2)DOM2(属性事件)

 一个元素只能绑定一个事件,且最后面绑定的事件会覆盖前面的内容。

例:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>事件级别 - DOM2</title>
        <script>
            window.onload = function(){
                var btn1=document.getElementById("btn1");
                var content=document.getElementById("content");
                btn1.onclick=function(){
                    alert("btn1_click");
                }
                btn1.onclick=function(){
                    alert("btn1_click2");
                }
                content.onclick=function(){
                    alert("content_click");
                }
            };
        </script>
    </head>
    <body>
        <div id="content">
            <p>content</p>
            <button id="btn1">btn1</button>
        </div>        
    </body>
</html>

此时,会先弹出btn1_click2,后弹出content_click。btn1_click这个事件没有被触发,但事件冒泡依然存在。

解除事件绑定:  btn1.onclick=null;

游览器兼容性:支持所有游览器

(3)DOM3(事件监听)

一个元素可以绑定多个事件,并按事件添加顺序先后执行。

例:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>事件级别 - DOM3</title>
        <script>
            window.onload = function(){
                var btn1=document.getElementById("btn1");
                var content=document.getElementById("content");
                btn1.addEventListener("click",function(){
                    alert("btn1");
                },false);
                btn1.addEventListener("click",function(){
                    alert("btn2");
                },false);
                content.addEventListener("click",function(){
                    alert("content");
                },false);
            };
        </script>
    </head>
    <body>
        <div id="content">
            <p>content</p>
            <button id="btn1">btn1</button>
        </div>        
    </body>
</html>

  运行结果:先弹出 btn1, 然后btn2,最后content;

  1)游览器兼容性:

  • IE游览器:绑定事件是 attachEvent,解除绑定是 detachEvent
  • 标准游览器:绑定事件是 addEventListener,解除绑定是 removeEventListener

代码兼容性写法:

var EventUtil = {
  // 绑定事件 addHandler:
function (element, type, handler) { if (element.addEventListener) { // 标准游览器 element.addEventListener(type, handler, false); } else if (element.attachEvent) { // IE游览器 element.attachEvent("on" + type, handler); } else { element["on" + type] = handler; } },
  // 移除事件 removeHandler:
function (element, type, handler) { if (element.removeEventListener()) { // 标准游览器 element.removeEventListener(type, handler, false); } else if (element.detachEvent) { // IE游览器 element.detachEvent("on" + type, handler); } else { element["on" + type] = null; } } };

2)addEventListener

语法:element.addEventListener(event, function, useCapture);

参数说明:

event,事件类型(如 "click" 或 "mousedown")

function,事件触发后调用的函数

useCapture,可选参数,布尔值,描述事件是冒泡还是捕获

3、事件对象(Event)

  事件对象,是用来记录一些事件发生时的相关信息的对象。

  (1)生命周期

随事件发生时产生,所有事件处理函数运行结束而被销毁

(2)对象属性

1)type属性

通过type我们可以获取事件发生的类型

2)target属性

target属性主要用于获取事件的目标对象

3)鼠标事件属性

在用鼠标触发事件时,主要的事件属性包含鼠标的位置和按键的状态

4)键盘事件属性

在用键盘触发事件时,主要的事件属性包含键盘的按键keyCode和是否按下特殊键

还有很多。。。

(3)对象方法

  1)阻止事件冒泡

标准游览器:stopPropagation();

function getEvent(event) {
   event.stopPropagation();
}
child.addEventListener('click', getEvent, false);

IE游览器:event.cancelBubble=true

兼容写法如下:

function getEvent(event) {
   event = event || window.event;
   if (event.stopPropagation) {
      event.stopPropagation();
   } else {
       event.cancelBubble = true;
   }
}

2) 阻止标签默认行为

标准游览器:preventDefault();

例:

<a id="go" href="https://www.baidu.com/">禁止跳转</a>

var go = document.getElementById('go');
function goFn(event) {
    event.preventDefault();
    console.log('我没有跳转!');
}
go.addEventListener('click', goFn, false);

IE游览器:event.returnValue=false

兼容写法如下:

function goFn(event) {
    event = event || window.event;
    if (event.preventDefault) {
        event.preventDefault();
    } else {
        event.returnValue = false;
    }
     console.log('我没有跳转!');
}

3)stopImmediatePropagation

stopImmediatePropagation()在阻止事件冒泡的同时,也把这个元素绑定的同类型事件也阻止了。


<a id="go" href="https://www.baidu.com/">禁止跳转</a>

var go = document.getElementById('go');

function goFn(event) {
    const event = event || window.event;
    event.preventDefault();
    event.stopImmediatePropagation(); // 阻止事件冒泡并阻止同类型事件
    console.log('我没有跳转!');
}
function goFn2(event) { console.log('我是同类型事件!'); }
go.addEventListener(
'click', goFn, false); go.addEventListener('click', goFn2, false);

 部分游览器不支持;

jQuery此类库库封装了跨平台的stopImmediatePropagation方法。

(4)对象兼容性

在IE8及以前本版之中,通过设置属性注册事件处理程序时,调用的时候并未传递事件对象,需要通过全局对象window.event来获取。解决方法如下:

function getEvent(event) {
  event = event || window.event;
}

4、事件委托

事件委托,就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

无需遍历所有子节点。

例:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>事件委托</title>
        <script>
            window.onload = function(){
                var btnAdd = document.getElementById('btnAdd');
                var ulList = document.getElementById('ulList');
                var num = 3;
                ulList.onclick = function(event){
                    var event = event || window.event;
                    var target = event.target || event.srcElement;
                    if(target.nodeName.toLowerCase() == 'li'){
                        alert(target.innerHTML);
                    }
                }
                btnAdd.onclick = function () {
                    num++;
                    var li = document.createElement('li');
                    li.innerHTML = num;
                    ulList.appendChild(li);
                    doclick();
                }
            };
        </script>
    </head>
    <body>
        <button id="btnAdd">添加</button>
        <ul id="ulList">
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
    </body>
</html>

这里用父级ul做事件处理,当li被点击时,由于冒泡原理,事件就会冒泡到ul上,因为ul上有点击事件,所以事件就会触发,当然,这里当点击ul的时候,也是会触发的,所以要判断点击的对象到底是不是li标签元素。

适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。

posted on 2019-10-16 14:01  布娃娃  阅读(123)  评论(0编辑  收藏  举报