js的事件处理机制

1、事件、监听、绑定、委派

①、什么是事件监听

DOM允许我们书写JS代码,来让HTML元素对事件作出反应;

事件:用户与网页的交互动作;eg:点击网页;

监听:是为了让计算机随时能够发现这个事件发生了,从而执行程序员预先编写的一些程序;

设置事件监听的方法主要有onxxx和addEventListener()两种;

②、最简单的设置事件监听的方法

设置它们的onxxx属性;

oBox.onclick = function () {
    // 点击盒子时,将执行这里的语句
}
常见的鼠标事件监听
        事件名 事件描述
        onclick 当鼠标单机某个对象
        ondblclick  当鼠标双击某个对象
        onmousedown 当某个鼠标按键在某个对象上被按下
        onmouseup   当某个鼠标按键在某个对象上被松开
        onmousemove 当某个鼠标按键在某个对象上被移动
        onmouseenter    当鼠标进入某个对象(相似事件onmouseover)
        onmouseleave    当鼠标离开某个对象(相似事件onmouseout)
        
常见的键盘事件监听
        事件名 事件描述
        onkeypress  当某个键盘的键被按下(系统按钮,如箭头键和功能键无法得到识别)
        onkeydown   当某个键盘的键被按下(系统按钮可以识别,并且会先于onkeypress发生)
        onkeyup 当某个键盘的键被松开
        
常见的表单事件监听
        事件名 事件描述
        onchange 当用户改变某个表单域的内容时,会触发
        onfocus 当某元素获得焦点(比如tab键或鼠标点击)
        onblur  当某元素失去焦点
        onsubmit    当表单被提交
        onreset 当表单被重置
        
常见的页面事件监听
        事件名 事件描述
        onload  当页面或图像被完成加载
        onunload    当用户退出页面

③、什么是事件的传播

先从外到内(捕获阶段),然后再从内到外(冒泡阶段)

而,onxxx这样的写法(DOM0级),只能监听冒泡阶段;所以需要用到addEventListener()方法(DOM2级);

oBox1.addEventListener('click', function(){
    // 这是事件处理函数
}, true)  
// true表示监听捕获阶段,false表示监听冒泡阶段

注意事项:

  • 最内部的元素不再区分捕获和冒泡阶段,会先执行写在前面的监听,然后执行后写的监听;

  • 如果给元素设置相同的两个或多个同名事件,则DOM0级写法后面写的会覆盖先写的;

  • 而DOM2级会按顺序执行;

④、什么是事件的绑定

  • 给元素对应的事件添加处理函数

  • 也就是捕获事件、处理事件

⑤、什么是事件委派

  1. 定义:把原本需要绑定在子元素的响应事件(click、keydown……)委托给父元素,让父元素担任监听的职务。

  2. 原理:DOM元素的事件冒泡

  3. 实现事件委托三部曲:

    • 把事件注册给上级。

    • 利用事件对象.target找到最先触发事件的元素。

    • 用nodeName判断这个元素是否我们所需要的。

  4. 优点:

    1. 可以大量节省内存占用,减少事件注册,比如:在ul上代理所有的li的click事件就非常棒。

    2. 可以实现当新增子对象时无需再次对其绑定(动态绑定事件)

  5. 注意事项

    • 使用“事件委托”时,并不是说把事件委托给的元素越靠近顶层就越好。

    • 事件冒泡的过程也需要耗时,越靠近顶层,事件的”事件传播链”越长,也就越耗时。如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失。

2、事件绑定的几种方式

①、标签-属性赋值

<button id="btn" οnclick="alertModal()">btn</button>
function alertModal(){
    console.log('我是btn,我被点击了!');
}
优点:
  • 简单易用

  • 必能绑定上事件,哪怕是动态生成的元素,这么加上也好使

缺点:
  • 可读性极差

  • 只可以绑定一个方法

  • 结构和行为耦合

  • 修改困难,比如好几个按钮同一个事件函数,需要逐行修改

  • 不建议使用

②、js代码-简单事件监听-DOM0级

<button id="btn">btn</button>
document.getElementById("btn3").onclick = Fn1
document.getElementById("btn3").onclick = Fn2
// 只能触发Fn2方法, 如果需要同时触发两个方法, 只能使用事件监听
优点:
  • 简单易用

缺点:
  • 本质和 标签-属性赋值 的方式一模一样,只不过这个属性从直接写在标签上,改成写在了js代码里

  • 所以直接写在标签上的缺点,它也同样都有

  • DOM0级写法,后写的会覆盖前写的

  • 并且,因为它不是直接写在标签上,且用了最原始的onclick方法,导致无法给动态元素添加事件

  • 总结:最垃圾的一种方式,绝对不要用

③、js代码-事件监听-DOM2级

④、jquery进行事件处理

1、bind() -- 不建议使用
  • 无法给动态生成的元素绑定事件

  • 选择器不够灵活

2、live() -- 已完全弃用

live() 方法在 jQuery 版本 1.7 中被废弃,在版本 1.9 中被移除。请使用 on() 方法代替。

3、on() -- 委托给祖先元素,建议使用
  • 灵活的选择器

  • 事件委派给祖先元素处理

3、父、子元素的事件捕获和执行顺序

整体流程:先捕获--->后冒泡

捕获:从外到内,祖先元素--->子元素

冒泡:从内到外,子元素--->祖先元素

结论:

  • 当一个事件触发时,父元素会先捕获到该事件,然后子元素才会捕获到

  • 但事件函数是在冒泡阶段执行的

  • 所以子元素的事件函数先执行,父元素的后执行

<body>
    <div>
        包含button的div
        <button>div中的button</button>
    </div>
    <script !src="">
        $('div').click(() => {
            console.log('我是div')
        });
​
        $('button').click(() => {
            console.log('我是button')
        });
    </script>
</body>
点击button按钮时执行结果:
我是button
我是div

4、var对于事件的影响

由于var的影响是函数之内,且会出现变量提升现象,所以有时候会对循环、动态生成的元素绑定事件产生不可测的影响

<div class="btn_container">
</div>
<script>
    let btnArr = [
        {name: 'btn1'},
        {name: 'btn2'},
        {name: 'btn3'}
    ]
    for (var i = 0; i < btnArr.length; i++) {
​
        let btnHtml = '<button class="' + btnArr[i]['name'] + '">' + btnArr[i]['name'] + '</button>'
        $(btnHtml).appendTo($('.btn_container'));
        $('.btn_container').on('click', '.' + btnArr[i]['name'], function (e) {
            console.log(e)
            console.log(e.target)
            console.log(i)
            alert(btnArr[i]['name'])
        })
        if (i == btnArr.length - 1) {
            break;
        }
    }
</script>
  • 如果循环体内的i是var修饰,则绑定的变量值都是 i=2

  • 如果i是用let修饰的,那么每个button绑定的变量值才是 具体的 0/1/2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值