DOM事件

本文深入解析DOM事件机制,包括鼠标事件、键盘事件等常见事件类型及其绑定方式。对比DOM0级和DOM2级事件绑定的区别,并介绍事件传播机制,如冒泡和捕获阶段。

DOM事件

  1. 事件及浏览器常用事件行为

给一个元素绑定 onclick onmouseenter onmouseleave window.onscroll img.onload window.onload 事件绑定,给元素绑定事件;当事件触发,执行对应函数

dom0级事件 dom2级事件 事件池机制以及其引出来的发布订阅者设计模式

事件:元素天生自带的默认行为。

天生自带的可进行的操作,不管你写没写onclick它都有click事件。

时间绑定:给元素的某个行为绑定一个方法

鼠标事件行为:

click 点击

dblclick 双击

mouseenter

mouseleave

键盘事件:

keyup

keypress

手指事件:

touch 单手指

touchstart 手指按下

touchend 手指松开

touchmove 手指移动

touchcancel 操作取消,用于非正常状态下的操作结束,滑动过快

多手指事件模型:

gesturestart 5个手指按下的信息都存起来

表单元素:

focus

blur

change

音视频常用事件:

canplay 可以播放

canplaythrough

其他常用事件:

load 资源加载完成。(document.ready dom结构渲染完成;window.onload 浏览器当前页面所有资源加载完成)

beforeunload 页面关闭之前

timeout 超时

onbort 中断事件

oncontextmenu 右键

  1. DOM 0级和2级 事件绑定的区别

onxxx dom 0级事件绑定

  1. 可绑定方法的数量

区别:

可绑定方法的数量:

dom0级:原理是私有属性赋值。当前元素对象的私有属性,赋值了一个方法;

dom2级:是把绑定的事件方法存到事件池中,绑定几个存几个

cec3d19899d5a9dd2ccc086dd491a420.png

4c9025b00f7bd08ae299f3daebce7b53.png

47b9dda332034a62e242d27c2508df09.png

操作上的区别:

onxxx=null

removeEventListener:因为移除时需要知道哪个函数,所以2级事件绑定一般采用实名函数

事件池会自动去重

  1. 顺序

二者可以混用,不冲突,都会被触发;

执行顺序就是按照你绑定的顺序;

  1. 支持的事件类型

DOM2支持的事件类型比dom0要多

比如,ontransitonend DOMContentLoaded

跟css3相关的一些东西,dom0里一般都支持不好

这里有2个比较重要的事件:load和DOMContentLoaded

2级的好处:

  1. 可以给当前某个事件行为绑定多个方法

  2. 支持更多强大的事件类型

jQuery中的事件绑定

on方法实现事件绑定

有一个专门的event去处理事件:event.on event.remove

752bacdb67783008a01ea111a7ec4621.pngd9c7a24b5ff7b3490a626b81fd63de3a.png46c88184350726ee37decd6f3beac52f.png81fa80cc5e5665ea441dd4e5bb2ebb5b.png

有一道题:

看过源码

本质区别

闭包是什么,怎么理解

  1. 事件对象

给原生绑定一个事件,触发click事件行为的时候,事件回调触发;

给元素的某个事件行为绑定方法,当事件触发,方法执行;不仅方法会执行,而且还会把当前你操作的信息传给方法,而传过来的信息就叫事件对象

MouseEvent 鼠标事件对象类,我们得到的是这个类的实例

KeyboardEvent 键盘事件类

  1. 一些属性

事件对象:你当前操作的相关信息,存储的是你当前操作相关信息

当前鼠标触发点距离窗口左上角的 x/y轴坐标值

clientX / clientY

pageX / pageY:距离文档流左上角的 x/y轴坐标值

target: 事件源

  1. 事件对象永远只有一个

事件对象永远都只有一个。从底层原理来看:

事件对象仅和当前操作有关,跟函数跟事件无关。

是由事件操作本身产生的,跟方法无关。

  1. preventDefault

阻止默认行为

a标签的默认行为:点击跳转链接或锚点定位

想把它当做普通按钮。阻止默认行为:

  1. return false;

  2. ev.preventDefault;

先触发click行为,再执行href跳转。

右键菜单:

document.documentElement.oncontextmenu=function(ev){
    ev.preventDefault();
    console.log(ev);
    const contextmenu=document.querySelector('.contextmenu');
    contextmenu.style.left=ev.clientX+'px';
    contextmenu.style.top=ev.clientY+'px';
    contextmenu.style.display='block';
}

<body>
    <ul class="contextmenu">
        <li>新建文档</li>
        <li>删除文档</li>
    </ul>
</body>

输入框禁止输入案例:

let inputEl=document.getElementById('cardInput');
inputEl.addEventListener('input',function(ev){
    this.value=this.value.replace(/([^0-9X])/gi,'')
})

let inputEl=document.getElementById('cardInput');
inputEl.addEventListener('keydown',function(ev){
    
    console.log(ev)
    let pass=/x|[0-9]/gi.test(ev.key)
    console.log(pass);
    if(!pass){
        ev.preventDefault();
    }
})

  1. KeyboardEvent

键盘事件对象:

cancelBubble 阻止冒泡

code 按的那个键。比key描述得更详细

keyCode | which 键盘里的每个键都有自己对应的键盘码值

按下键能往文本框输入内容——这属于按键的默认行为

那现在阻止这个默认行为,输不进去内容,超过多少位不让输了

a标签的默认行为、右键默认行为、文本框按键输入默认行为

  1. 推盒子案例

小方块在一个容器里来回走

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>pushbox</title>
    <style>
        .container{
            width: 500px;
            height: 500px;
            background: #9fcdff;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
        }
        .container .box{
            width: 100px;
            height: 100px;
            background: #a71d2a;
            position: absolute;
            top: 0;
            left: 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="box"></div>
    </div>
    <script>
        let container=document.querySelector('.container'),box=document.querySelector('.box');
        let step=10;

        document.addEventListener('keydown',function (ev) {
            let left=box.offsetLeft;
            let top=box.offsetTop;
            let minLeft=0,maxLeft=container.offsetWidth-box.offsetWidth,minTop=0,maxTop=container.offsetHeight-box.offsetHeight;
            switch (ev.keyCode) {
                case 37:
                    if(left>minLeft){
                        left-=step;
                    }
                    break;
                case 38:
                    if(top>minTop){
                        top-=step;
                    }
                    break;
                case 39:
                    if(left<maxLeft){
                        left+=step;
                    }
                    break;
                case 40:
                    if(top<maxTop){
                        top+=step;
                    }
                    break;
            }
            box.style.top=`${top}px`;
            box.style.left=`${left}px`;
        })
    </script>
</body>
</html>

贪吃蛇:碰到了长度加长,让蛇身能拐弯,大部分都是算法处理

  1. 事件的传播机制

不仅当前元素的事件行为被触发,它所有祖先元素的相关事件行为都会被依次触发。

冒泡传播机制:

触发当前元素的某一个事件行为,所有祖先元素相关的事件行为都会依次触发从内向外传播。

center -> inner -> outer -> body -> html -> document -> window ......

谁的click行为绑定过方法,谁就会被触发

事件对象一样,事件源一样。target:事件源都是center

3d14b7aaef693f131acd6fd2ba025ac9.png

冒泡是最后一个阶段,之前还有2个阶段。

捕获阶段:从body开始,一层层往里找;

Event原型上记录了这几个值

捕获阶段的目的:就是为了构建path传播路径;

dom 0级事件绑定:只能在目标阶段和冒泡阶段触发执行;

dom 2级事件:为true为在捕获阶段执行;默认false,在冒泡阶段执行

总结:

当前元素的某一事件行为触发总要经历3个阶段:

捕获:从外到里找到事件源

目标:当前事件源事件行为触发,事件回调执行

冒泡:按照捕获阶段构建的路径,从内到外一层层传播。所有祖先行为依次触发,如果绑定方法,方法执行

  1. mouseover和mouseenter的本质区别

无法说:mouseover干什么,mouseout干什么;

父元素->子元素,其实你还在父元素上面,

仅仅是从父元素滑到子元素,父元素既触发一次mouseout,又触发一次mouseover;

enter和leave 两大区别:

enter和leave默认阻止了冒泡传播;

从父元素->子元素,就不存在什么 leave再enter;

  1. 快速回顾

blur focus load scroll 默认阻止了冒泡传播

很多天生就有,很多天生就阻止了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值