zoukankan      html  css  js  c++  java
  • JavaScript DOM 事件

    1.注册事件(绑定事件)

    1.1 注册事件概述

    给元素添加事件 成为注册事件或者绑定事件。

    注册事件有两种方式 传统方式和方法监听注册。

    传统注册方式:

    利用on开头的事件 onClick

    例如 <button onClick = 'alert('hi')'></button>  button.onClick =function()

    特点:注册事件的唯一性 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数.

    方法监听注册方式:

    w3c标准 推荐方式

    addEventListener() 他是一个方法 IE9之前不兼容  用的是attacEvent()代替。

    特点:同一个元素同一个事件可以注册多个监听器 按注册顺序依次执行

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <button>传统注册事件</button>
        <button>方法监听注册事件</button>
        <button>IE9之前</button>
        <script>
            var btns = document.querySelectorAll('button');
            btns[0].onclick = function () {
                alert('哈哈哈');
            }
            //覆盖前一个
            btns[0].onclick = function () {
                alert('嘻嘻嘻');
            }
    
            btns[1].addEventListener('click', function () {
                alert('哇哇哇');
            })
            btns[1].addEventListener('click', function () {
                alert('噜噜噜');
            })
    
            // addEventListener(type,listener,[,useCapture])
            // type 事件类型的字符串 比如click mouseover 注意这里不要带on
            // listener 事件处理函数 事件发生时 会调用该监听函数
            // useCapture 可选参数 是一个bool值 默认是false 
    
            //IE9之前不支持addEventListener 使用attachEvent()代替 但是是非标准的 尽量不要再生产环境中使用
            //attachEvent(eventNameWithOn,callBack);
            //eventNameWithOn 事件类型字符串 比如 onclick onmouseover 这里要改on
            //callBack 事件处理函数 当目标出发事件时回调函数被调用
            btns[2].attachEvent('onclick',function() {
                alert('IE9');//只能IE9符合条件 其他浏览器也不识别
            })
        </script>
    </body>
    
    </html>

    注册事件兼容性解决方案:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <button>各个浏览器都可以</button>
        <script>
            //兼容性处理原则 首先处理大多数浏览器 再处理特殊浏览器
            var btn = document.querySelector('button');
            var fn = function btnClick() {
                alert('我被点击了');
            }
            addEventListener1(btn, 'click', fn);
    
            function addEventListener1(element, eventName, fn) {
                if (element.addEventListener) {
                    element.addEventListener(eventName, fn);
                } else if (element.attachEvent) {
                    element.attachEvent('on' + eventName, fn)
                } else {
                    element['on' + eventName] = fn
                }
            }
        </script>
    </body>
    
    </html>

    删除事件(解绑事件)

    传统注册方式 可以使用 eventTarget.onclick = null 来解除绑定的事件。

    方法监听注册方式 可以使用eventTarget.removeEventListener(type,listener,[useCapture]);来解除绑定事件.

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div {
                width: 100px;
                height: 100px;
                background-color: pink;
            }
        </style>
    </head>
    
    <body>
        <div>1</div>
        <div>2</div>
        <div>3</div>
        <script>
            var divs = document.querySelectorAll('div');
            divs[0].onclick = function () {
                alert('哈哈哈');
                divs[0].onclick = null;
            }
            divs[1].addEventListener('click', fn);
    
            function fn() {
                alert('嘻嘻嘻');
                divs[1].removeEventListener('click', fn);
            }
            //只在IE9以下浏览器适用
            divs[2].attachEvent('onclick', fn1);
    
            function fn1() {
                alert('嘿嘿嘿')
                divs[2].detachEvent('onclick', fn1);
            }
            //兼容性的移除函数
            function removeEventListener(element,eventName,fn) {
                if (element.removeEventListener) {
                    element.removeEventListener(eventName,fn);
                }else if (element.detachEvent) {
                    element.detachEvent('on' + eventName,fn);
                }else {
                    element['on' + eventName] = null;
                }
            }
        </script>
    </body>
    
    </html>

    DOM事件流

    事件流描述的是从页面中接收事件的顺序

    事件发生时会在元素节点之间按照特定的顺序传播 这个传播过程即DOM事件流

    比如我们给一个div注册了点击事件:

    1.捕获阶段 2.当前目标阶段 3 冒泡阶段

    事件冒泡:IE最早提出 事件开始时由最具体的元素接收 然后逐级向上传播到DOM最顶层节点的过程

    事件捕获:网景最早提出 有DOM最顶层节点开始 然后逐级向下传播到最具体的元素接收的过程.

    注意:

    js代码中只能执行捕获或者冒泡其中的一个阶段

    onclick 和 attachEvent 传统的 只能得到冒泡阶段

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .father {
                width: 200px;
                height: 200px;
                background-color: purple;
                overflow: hidden;
            }
    
            .son {
                width: 100px;
                height: 100px;
                background-color: pink;
                margin: 50px;
            }
        </style>
    </head>
    
    <body>
        <div class="father">
            <div class="son"></div>
        </div>
        <script>
            // dom 事件流三个阶段
            // 1.js代码中只能执行捕获或者冒泡其中的一个阶段
            // 2.onclick 和 attachEvent(IE) 只能得到冒泡
            var son = document.querySelector('.son')
            // 第三个参数:true 处于捕获阶段 false 处于冒泡阶段
            //body->father->son
            son.addEventListener('click', function () {
                alert('son');
            }, true)
            var father = document.querySelector('.father');
            father.addEventListener('click', function () {
                alert('father');
            }, true)
            //上面的可以看到 先弹出了father 后弹出了son  因为是时间处于捕获阶段 所以先触发了父亲
            son.addEventListener('click', function () {
                alert('son');
            }, false)
            var father = document.querySelector('.father');
            father.addEventListener('click', function () {
                alert('father');
            }, false)
            //上面的先弹出 son 在弹出 father 因为处于冒泡阶段
        </script>
    </body>
    
    </html>

    实际开发中我们很少使用事件捕获 我们更关注事件冒泡

    有些事件是没有冒泡的 比如 onblur onfocus onmouseover  onmouseleave

    事件冒泡有时候会带来麻烦 有时候又会很有用 

    事件对象

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <div>123</div>
        <script>
            var div = document.querySelector('div');
            // event 就是一个事件对象 写到我们监听函数的小括号里面 当形参来看
            // 事件对象只有有了事件才会存在
            // 他是系统给我们自动创建的 不需要我们传递参数
            // 事件对象 使我们时间的一系列相关数据的结合 跟事件相关的 比如说鼠标点击里面就包含了鼠标的相关信息 鼠标坐标什么的 如果是键盘事件里面就包含了键盘事件的信息 比如用户按下了哪个键
            div.onclick = function (event) {
                console.log(event);
                //可以点击自行查看 有很多信息
            }
            //事件对象也有兼容性问题 IE678通过window.event获取
            // IE678
            div.onclick = function (event) {
                console.log(window.event);
                //可以点击自行查看 有很多信息
            }
            //兼容性写法
            div.onclick = function (event) {
                event = event || window.event
            }
    
        </script>
    </body>
    
    </html>

    事件对象的常见属性和方法

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div {
                width: 100px;
                height: 100px;
                background-color: pink;
            }
        </style>
    </head>
    
    <body>
        <div>123</div>
        <ul>
            <li>abc</li>
            <li>abc</li>
            <li>abc</li>
        </ul>
        <script>
            // 常见事件对象的属性和方法
            var div = document.querySelector('div');
            div.addEventListener('click', function (e) {
                console.log(e.target); //返回触发事件的元素
                console.log(this) //返回的是绑定事件的对象
            })
            var ul = document.querySelector('ul');
            //了解this 有个非常相似的属性 currentTarget 指定的是绑定事件的元素 IE678不兼容
            ul.addEventListener('click', function (e) {
                console.log(e.target);//li 返回的是触发事件的元素 
                console.log(this); //ul 绑定事件的元素
                console.log(e.currentTarget); //返回绑定事件的元素
            })
            //区别:e.target 点击了什么 返回什么 this 谁绑定的返回谁
            //e.target 也是有兼容性的
            //兼容性写法 只能这样
            div.onclick = function(e) {
                e = e || window.event;
                var target = e.target || e.srcElement;
                console.log(target)
            }
        </script>
    </body>
    
    </html>
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            div {
                width: 100px;
                height: 100px;
                background-color: pink;
            }
        </style>
    </head>
    
    <body>
        <div>123</div>
        <a href="http://www.baidu.com">百度</a>
        <form action="http://www.baidu.com">
            <input type="submit" value="提交" name="sub">
        </form>
        <script>
            var div = document.querySelector('div');
            div.addEventListener('click', function (e) {
                console.log(e.type); //click
            })
            //阻止默认行文 让链接不跳转 或者让提交按钮不提交
            var a = document.querySelector('a');
            a.addEventListener('click', function (e) {
                e.preventDefault();//dom标准写法 IE低版本不支持
            })
            //传统的注册方式 可以兼容IE低版本
            a.onclick = function (e) {
                // //普通浏览器
                // e.preventDefault();
                // //低版本浏览器
                // e.returnValue;
                //我们还可以利用return false 阻止默认行为 没有兼容性问题 但是return后面的代码不执行了 而且只限于传统注册方式
                return false
            }
        </script>
    </body>
    
    </html>

    阻止事件冒泡 开始由最具体的接收元素 然后逐级向上传播到DOM最顶层节点。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            .father {
                width: 200px;
                height: 200px;
                background-color: purple;
                overflow: hidden;
            }
    
            .son {
                width: 100px;
                height: 100px;
                background-color: pink;
                margin: 50px;
            }
        </style>
    </head>
    
    <body>
        <div class="father">
            <div class="son"></div>
        </div>
        <script>
            // dom 事件流三个阶段
            // 1.js代码中只能执行捕获或者冒泡其中的一个阶段
            // 2.onclick 和 attachEvent(IE) 只能得到冒泡
            var son = document.querySelector('.son')
            // 第三个参数:true 处于捕获阶段 false 处于冒泡阶段
            //body->father->son
    
            //上面的可以看到 先弹出了father 后弹出了son  因为是时间处于捕获阶段 所以先触发了父亲
            son.addEventListener('click', function (e) {
                alert('son');
                // //阻止事件冒泡
                // e.stopPropagation(); //不会再执行father的方法
                // //低版本的浏览器 是这样的
                // e.cancelBubble;
                //兼容性写法
                if (e && e.stopImmediatePropagation) {
                    e.stopPropagation();
                } else {
                    window.event.cancelBubble;
                }
            }, false)
            var father = document.querySelector('.father');
            father.addEventListener('click', function () {
                alert('father');
            }, false)
        </script>
    </body>
    
    </html>

    时间委托(代理,委派)

    事件冒泡本身的特性,会带来坏处 也会带来好处 需要我们灵活掌握

    事件委托也称为事件代理 在JQuery里面成为事件委派

    事件委托的原理:

    不是每个子节点单独设置事件监听器 而是事件监听器设置在其父节点上 然后利用冒泡原理影响设置每个子节点

    例如所有的li都有一个共同的事件 我们不能每个li都给一个监听事件 我们可以利用冒泡原理给ul一个事件,来完成这个需求。

    事件委托的作用

    按照上述例子 我们只操作了一次DOM 提高了程序的性能。

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <ul>
            <li>知否知否</li>
            <li>知否知否</li>
            <li>知否知否</li>
            <li>知否知否</li>
            <li>知否知否</li>
        </ul>
        <script>
            var ul = document.querySelector('ul');
            ul.addEventListener('click', function (e) {
                alert('知否知否');
                e.target.style.backgroundColor = 'pink';
            })
        </script>
    </body>
    
    </html>

    常用的鼠标事件

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        我是一段不愿意被分享的文字
        <script>
            // 禁止鼠标右键菜单
            // contentmenu主要控制应该何时显示上下文菜单 主要用于城御园取消默认的上下文菜单
            // contextmenu 禁止使用右键菜单
            document.addEventListener('contextmenu', function (e) {
                e.preventDefault(); //阻止默认行为
            })
            // 禁止选中 selectstart;
            document.addEventListener('selectstart', function (e) {
                e.preventDefault();
            })
        </script>
    </body>
    
    </html>

    event对象代表事件的状态 跟事件相关的一系列信息的集合 现阶段我们主要是用鼠标事件对象

    MouseEvent和键盘事件对象keyboardEvent

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <style>
            img {
                position: absolute;
                top: 2px;
            }
        </style>
    </head>
    
    <body>
        <img src="../img/angel.gif" alt="">
        <script>
            var img = document.querySelector('img');
            document.addEventListener('mousemove', function (e) {
                var x = e.pageX;
                var y = e.pageY;
                img.style.top = y - 40 + 'px';
                img.style.left = x - 50 + 'px';
            })
        </script>
    </body>
    
    </html>

    常用的键盘事件

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    
    <body>
        <script>
            // keyup 按键弹起时触发
            document.onkeyup = function () {
                alert('我叹气了');
            }
            // keydown 按键按下的时候触发 按着键不松一直触发
            document.onkeydown = function () {
                console.log('按下了')
            }
            // keypress 按键按下的时候触发
            document.onkeypress = function () {
                console.log('按下了')
            }
            // keypress 不识别功能键 ctrl  shift 左右箭头等
            // keydown  什么都能够识别 包括功能键
        </script>
    </body>
    
    </html>

    键盘事件对象

    keyup和keydown 事件不区分字母大小写 e.keyCode 得到按键对应的ASCII码

    keypress 区分大小写.

  • 相关阅读:
    多播委托与事件
    Linq 查询的演变过程
    Lamda表达式的前世今生
    微服务架构学习
    委托IL解析-----封装逻辑和代码复用
    ORM框架学习(四)
    ORM框架学习(三)
    Visual Studio 2010 旗舰版安装图解
    Microsoft SQL Server 2008 R2 中文安装说明
    3.0 面向对象 委托和事件 异常和错误
  • 原文地址:https://www.cnblogs.com/huanying2000/p/12748251.html
Copyright © 2011-2022 走看看