【JavaScript】事件高级

注册事件

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

传统方式注册

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

addEventListener事件监听方式

eventTarget.addEventListener()方法将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
特点:同一个元素同一个事件可以注册多个监听器,按注册顺序依次执行。
语法

eventTarget.addEventListener(type,listener[,useCapture])

参数
type:事件类型字符串,比如click,mouseover,注意这里不要带on
listener:事件处理函数,事件发生时,会调用该监听函数
useCapture:可选参数,是一个布尔值,默认是 false。

attachEvent事件监听方式

与eventTarget.addEventListener()方法类似,不过参数不一样

语法

eventTarget.attachEvent(eventNameWithOn,callback)

参数
eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
callback: 事件处理函数,当目标触发事件时回调函数被调用

缺点:ie9以前的版本支持

<body>
    <button>传统注册事件</button>
    <button>addEventListener</button>
    <button>attachEvent</button>
    <script>
        var btns = document.querySelectorAll('button');
        // 1. 传统方式注册事件
        // 只执行后面的
        btns[0].onclick = function() {
      
      
            alert('1');
        }
        btns[0].onclick = function() {
      
      
                alert('2');
            }
            // 2. 事件监听注册事件 addEventListener 
            // 两个都会依次执行
        btns[1].addEventListener('click', function() {
      
      
            alert(22);
        })
        btns[1].addEventListener('click', function() {
      
      
            alert(33);
        })
            // 3. attachEvent ie9以前的版本支持
        btns[2].attachEvent('onclick', function() {
      
      
            alert(11);
        })
    </script>
</body>

删除事件

传统方式删除事件

eventTarget.onclick = null;

removeEventListener删除事件方式

eventTarget.removeEventListener(type,listener[,useCapture]);

参数与addEventListener事件监听方式的参数相同

detachEvent删除事件方式

eventTarget.detachEvent(eventNameWithOn,callback);

参数与attachEvent事件监听方式的参数相同

<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs = document.querySelectorAll('div');
        divs[0].onclick = function() {
      
      
            alert(11);
            // 1. 传统方式删除事件
            divs[0].onclick = null;
        }
        // 2.removeEventListener 删除事件
        //里面的fn不需要调用加小括号,返回的是函数,加括号是调用
        divs[1].addEventListener('click',fn);   

        function fn(){
      
      
            alert(22);
            divs[1].removeEventListener('click',fn);
        }
        // 3.IE9 中的删除事件方式
        divs[2].attachEvent('onclick',fn1);
        function fn1() {
      
      
            alert(33);
            divs[2].detachEvent('onclick',fn1);
        }
    </script>
</body>

DOM事件流

事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流。
DOM事件流分为3个阶段:

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

理解

注意:JS 代码中只能执行捕获或者冒泡其中的一个阶段,不能同时执行。

事件捕获阶段

在事件捕获过程中,document对象首先接收到click事件,然后事件沿着DOM树依次向下,一直传播到事件的实际目标。
即document -> html -> body -> div

<body>
    <div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
      // 如果addEventListener 第三个参数是 true 那么则处于捕获阶段
        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
      
      
             alert('son');
        }, true);
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
      
      
            alert('father');
        }, true);
    </script>
</body>

此时点击子盒子,会先弹出 father,之后再弹出 son。

事件冒泡阶段

事件开始时有最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
即div -> body -> html -> document

<body>
    <div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
		// 如果addEventListener 第三个参数是 false或省略 那么则处于冒泡阶段
        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
      
      
            alert('son');
        }, false);
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
      
      
            alert('father');
        }, false);
        document.addEventListener('click', function() {
      
      
            alert('document');
        })
    </script>
</body>

此时点击子盒子,会先弹出 son,之后再弹出 father。

事件对象

事件对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
如:

eventTarget.onclick = function(event) {
} 

event就是此事件的事件对象

事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,事件对象有很多属性和方法:

  1. 谁绑定了这个事件
  2. 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置
  3. 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键

注意:event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去;当我们注册事件时, event 对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)

事件对象的兼容性问题
事件对象本身的获取存在兼容问题:

  • 标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。
  • 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找

解决:

<body>
    <div>123</div>
    <script>
        // 事件对象
        var div = document.querySelector('div');
        div.onclick = function(e) {
      
      
          // 解决兼容性问题
                // console.log(e);
                // console.log(window.event);
                // e = e || window.event;
                console.log(e);
            }
    </script>
</body> 

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

事件对象属性方法 说明
e.target 返回触发事件的对象 标准
e.srcElement 返回触发事件的对象 非标准 ie6-8使用
e.type 返回事件的类型 比如click mouseover 不带on
e.cancelBubble 该属性阻止冒泡,非标准,ie6-8使用
e.returnValue 该属性阻止默认行为 非标准,ie6-8使用
e.preventDefault() 该方法阻止默认行为 标准 比如不让链接跳转
e.stopPropagation() 阻止冒泡 标准

e.target 和 this 的区别:

  • this 是事件绑定的元素, 这个函数的调用者(绑定这个事件的元素)
  • e.target 是事件触发的元素。

事件对象阻止默认行为
html中一些标签有默认行为,例如a标签被单击后,默认会进行页面跳转。可以通过事件对象阻止这种默认行为。
方法

  1. e.preventDefault() 方法 DOM标准
  2. returnValue 属性 低版本浏览器 ie678适用
  3. return false 传统的注册方式,return 后面的代码不能执行
<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>
        // 1. 返回事件类型
        var div = document.querySelector('div');
        div.addEventListener('click', fn);
        div.addEventListener('mouseover', fn);
        div.addEventListener('mouseout', fn);

        function fn(e) {
      
      
            console.log(e.type);

        }  
        // 2. 阻止默认行为(事件) 让链接不跳转 或者让提交按钮不提交
        var a = document.querySelector('a');
        a.addEventListener('click', function(e) {
      
      
                e.preventDefault(); //  dom 标准写法
            })
            // 3. 传统的注册方式
        a.onclick = function(e) {
      
      
            return false;
            alert(11);
        }
    </script>
</body>

阻止事件冒泡

方法

  1. 标准写法:利用事件对象里面的 e.stopPropagation()方法
  2. 非标准写法:IE 6-8 利用事件对象 cancelBubble 属性 e.cancelBubble = true;
<body>
    <div class="father">
        <div class="son">son儿子</div>
    </div>
    <script>
        // 阻止冒泡  dom 推荐的标准 stopPropagation() 
        var son = document.querySelector('.son');
        son.addEventListener('click', function(e) {
      
      
            alert('son');
            e.stopPropagation(); // stop 停止  Propagation 传播
            e.cancelBubble = true; // 非标准 cancel 取消 bubble 泡泡
        }, false);

        // 点击father仍会冒泡,所以father也要添加
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
      
      
            alert('father');
        }, false);
        document.addEventListener('click', function() {
      
      
            alert('document');
        })
    </script>
</body>

事件委托

事件委托也称为事件代理,在 jQuery 里面称为事件委派

为什么要用事件委托

DOM需要有事件处理程序,我们都会直接给它设事件处理,但是如果有非常多的DOM需要添加事件,比如100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,然后给它们添加事件,但是这样做会有很大的缺点:

  1. 操作DOM次数过多,造成浏览器的重排和重绘就越多;
  2. 每个事件都是一个对象,事件处理程序越多,占用的内存越多,影响前端性能;

事件委托原理——事件冒泡

事件委托利用事件冒泡(从最深的节点开始,然后逐步向上传播事件)只在他们的父元素上指定一个事件处理程序,就可以管理某一类型的的所有事件。

<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
    <script>
        // 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
      
      
            // e.target 这个可以得到我们点击的对象
            e.target.style.backgroundColor = 'pink';
            // 如果点了全部则ul全是pink色
            // 点了谁,就让谁的style里面的backgroundColor颜色变为pink
        })
    </script>
</body>

常见鼠标事件

鼠标事件 触发条件
onclick 鼠标点击左键触发
onmouseover 鼠标经过触发
onmouseout 鼠标离开触发
onfocus 获得鼠标焦点触发
onblur 失去鼠标焦点触发
onmousemove 鼠标移动触发
onmouseup 鼠标弹起触发
onmousedown 鼠标按下触发

禁止鼠标右键与鼠标选中
contextmenu主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
selectstart 禁止鼠标选中

<body>
    <p>文字</p>
    <script>
        // 1. 禁用右键菜单
        // 点击右键不能显示菜单
        document.addEventListener('contextmenu', function(e) {
      
      
                e.preventDefault(); // 阻止默认行为
            })
            // 2. 禁止选中文字 
        document.addEventListener('selectstart', function(e) {
      
      
            e.preventDefault();
        })
    </script>
</body>

鼠标事件对象

鼠标事件对象 说明
e.clientX 返回鼠标相对于浏览器窗口可视区的X坐标
e.clientY 返回鼠标相对于浏览器窗口可视区的Y坐标
e.pageX(一般使用) 返回鼠标相对于文档页面的X坐标 IE9+ 支持
e.pageY(一般使用) 返回鼠标相对于文档页面的Y坐标 IE9+ 支持
e.screenX 返回鼠标相对于电脑屏幕的X坐标
e.screenY 返回鼠标相对于电脑屏幕的Y坐标

常见键盘事件

键盘事件 触发条件
onkeyup 某个键盘按键被松开时触发
onkeydown 某个键盘按键被按下时触发
onkeypress 某个键盘按键被按下时触发,但是它不识别功能键,比如 ctrl shift 箭头等

三个事件的执行顺序是: keydown – keypress — keyup
键盘事件对象

键盘事件对象 说明
e.keyCode 返回该键值的ASCII值

猜你喜欢

转载自blog.csdn.net/btufdycxyffd/article/details/127425109