事件的绑定与解绑

356 阅读3分钟

事件的概念

事件

元素在某种状态(某种状态由浏览器实现也称为事件触发)达成时,要执行的提前设定好的程序,称之为事件句柄。

事件三要素

1.事件源:在哪个元素上发生的。比如: p标签、a标签、div标签、form表单等

2.事件类型:到底发生了什么事件。click(点击事件)、mouseover(鼠标事件)、focus(焦点事件)等

3.事件处理程序(handler):事件源触发事件后,如何回应发生的事件,通常以函数(funtion)的形式来出现,要执行的提前设定好的程序。

ps:1.事件不是以 on 开头的那个名称,如 onclick 不是事件,click才是事件。onclick引用的是一个元素对象的属性,它指向click事件类型绑定的实际处理函数。

2.事件三要素缺一不可

事件的绑定

事件绑定的方式有3种:行内式,元素属性绑定,给元素添加一个事件监听器。

行内式

行内式是直接在html元素上进行绑定,即以属性的方式直接写在行内。

    <div class="box1">
        <button class="btn1" onclick="test();fn()">方式1</button>
    </div>
    <script>
        function  test(){
            console.log("test函数执行成功");
        };
        function fn(){
            console.log("fn函数执行成功");
        };
    </script>

代码演示效果

image.png

1.标签的属性值是事件触发时执行的代码,可以绑定多个事件处理程序,用分号隔开即可,按照顺序执行。

2.标签的属性值在事件没有触发前就是一串字符串,当事件触发后才是事件触发时执行的代码,js的执行引擎就会运行这个函数体中的代码。

缺点:HTML与js代码紧密相关。如果要更换事件,需要改动两个地方:HTML代码和JS代码,这就不利于后期代码的维护。

元素属性绑定

用元素.on事件=某个函数 绑定,需要先获取要绑定的元素。

    <div class="box2">
        <button class="btn2">方式2</button>
    </div>
    <script>
        let btn=document.querySelector(".btn2");
        btn.onclick=()=>{
            console.log("点击事件触发成功");
        };
    </script>

image.png

同一个 dom 元素上,on 只能绑定一个同类型事件,后者会覆盖前者,不同类型的事件可以绑定多个。

    <div class="box2">
        <button class="btn2">方式2</button>
    </div>
    <script>
        let btn=document.querySelector(".btn2");
        btn.onclick=()=>{
            console.log("点击事件触发成功");
        };
        btn.onclick=()=>{
            console.log("同类型事件会后者覆盖了前者");
        };

image.png

给元素添加事件监听器

给元素添加一个事件监听器(就是函数),同样需要先获取元素

同一个 dom 元素上,用 addEventListener()、attachEvent() 可以绑定多个同类型事件且行内的属性值也不会被覆盖。但是,addEventListener 事件执行顺序按照事件绑定的先后顺序执行;attachEvent 事件执行顺序则是随机的。

事件监听是唯一可以改变[事件的传播]方式的绑定方法,只用在第三个参数加上true,这样默认在冒泡阶段执行就会变为在捕获阶段执行

addEventListener()以及其参数

addEventListener()是异步非阻塞函数,异步非阻塞函数只能由官方提供,自定义的回调函数是异步阻塞函数。

第1个参数:是字符串填写事件类型名称,没有on。比如onclick ,onmouseover等

第2个参数:是回调函数作为事件处理程序的函数。当事件触发时才会调用回调函数,执行事件处理程序函数中的函数体

第3个参数:是布尔值。若为false,函数在冒泡阶段执行;若为true,函数在捕获阶段执行。可选参数,不填默认为false。

    <div class="box3">
        <button class="btn3">方式3</button>
    </div>
    <script>
        let btn=document.querySelector(".btn3");
        btn.addEventListener("click",()=>{
            console.log("事件被触发");
        });
    </script>

image.png

attachEvent()

attachEvent有兼容问题,谷歌火狐不支持以及IE11不支持,低版本的IE8支持。(目前IE浏览器已被淘汰)

addEventListener、attachEvent的区别

1)参数个数不一致

addEventListener三个参数,attachEvent两个参数

2)兼容问题

addEventListener 谷歌,火狐,IE11支持,IE8不支持

attachEvent 谷歌火狐不支持,IE11不支持,IE8支持

3)this指向不同

addEventListener 中的this是当前绑定事件的对象

attachEvent中的this是window

4)事件命名不同

addEventListener中事件的类型(事件的名字)没有on

attachEvent中的事件的类型(事件的名字)有on

解决兼容问题

    <button id="btn">btn</button>
    <script>
        //为任意元素.绑定任意的事件,
        //传入的el是任意的元素,type是事件的类型,fn是事件处理函数,
        //arg是addEventListener()的第3个参数,不传,默认为false
        function myaddEventListener(el, type, fn, arg) {
            if (arg == undefined) {
                arg = false;
            };
            //判断浏览器是否支持这个方法
            if (el.addEventListener) {
                el.addEventListener(type, fn, arg);
                console.log("支持addEventListener");
            } else if (el.attachEvent) {
                el.attachEvent("on" + type, fn);
                console.log("支持attachEvent");
            } else {
                el["on" + type] = fn;
                console.log("addEventListener和attachEvent都不支持");
            };
        };
        //测试
        myaddEventListener(document.getElementById("btn"), "click", function () {
            console.log("jzx");
        });
        myaddEventListener(document.getElementById("btn"), "click", function () {
            console.log("phm");
        });
        myaddEventListener(document.getElementById("btn"), "click", function () {
            console.log("gloria");
        });
    </script>

谷歌浏览器中运行结果

image.png

事件的解绑

元素.on 事件名字=null

行内式绑定和元素属性绑定的解绑,直接将属性值置空。

    <div class="box2">
        <button class="btn2">方式2</button>
    </div>
    <script>
        let btn=document.querySelector(".btn2");
        btn.onclick=()=>{
            btn.onclick=null;
            console.log("同类型事件会后者覆盖了前者");
        };
    </script>

image.png

点击事件触发后先将元素.on 事件名字的属性值设为空,这样点击事件只会触发1次,除非再次刷新页面可再次触发1次。

    <div class="box1">
        <button class="btn1" onclick="test();fn()">方式1</button>
    </div>
    <script>
        function  test(){
            console.log("test函数执行成功");
        };
        function fn(){
            console.log("fn函数执行成功");
        };
        let btn=document.querySelector(".btn1");
        btn.onclick=null;
    </script>

行内式同理,置空后当点击按钮时没有任何反应。

元素.removeEventListener()

需要移除什么元素的事件就用什么元素调用removeEventListener()。解绑事件的时候,需要在绑定事件的时候,使用命名函数,解绑的时候使用函数名。

参数

第1个参数:事件类型名称,没有on。

第2个参数:函数名,要和 addEventListener 指向同一个函数才能解绑成功。

第3个参数也是布尔值。

    <div class="box3">
        <button class="btn3">btn1</button>
        <button class="btn">btn2</button>
    </div>
    <script>
        let btn=document.querySelector(".btn3");
        let btn1=document.querySelector(".btn");
        let fg=()=>{
            console.log("gloria");
        };
        btn.addEventListener("click",fg);
        let fn=()=>{
            btn.removeEventListener("click",fg)
            console.log("第一个按钮点击事件解绑成功");
        };
        btn1.addEventListener("click",fn);
    </script>

image.png

元素.detachEvent()

用attachEvent绑定用元素.detachEvent(“on事件类型”,函数名字);(IE)

解决兼容问题的解绑

        //为任意的一个元素,解绑对应的事件
        function myremoveEventListener(el, type, fnName, arg) {
            if (arg == undefined) {
                arg = false;
            };
            if (el.removeEventListener) {
                el.removeEventListener(type, fnName, arg);
            } else if (el.detachEvent) {
                el.detachEvent("on" + type, fnName);
            } else {
                el["on" + type] = null;
            };
        };