灵魂拷问:用惯了Vue/React事件绑定的你,还记得js原生事件绑定么?
JS事件绑定
当我们在控制台上打印页面中的任意一个DOM,会发现输出的属性中有很多on***。这些都是浏览器暴露给js客户端,用于操作DOM和其他一些网络操作的接口,统称Web API。 在JS中,事件绑定通常有三种方式
- 在DOM元素中直接绑定
- 在JS中进行绑定
- 绑定事件监听函数
一、在DOM中直接绑定事件
例如最常见的单击(onclick)、鼠标移入(onmouseenter)、鼠标移出(onmouseout)等事件,都可以在HTML中直接指定。
<button onclick="func()">Click</button>
<script type="text/javascript">
let func = () => {
alert("click me")
}
</script>
此种方法是将js事件与HTML标签写在一起,不利于项目的管理维护。
二、在JS中进行事件绑定
为了使代码的结构更加清晰,可以按照不同的功能将HTML和js进行分离,提高效率。这种事件绑定方式也叫做DOM0级事件绑定
<button id="btn">Click</button>
<script type="text/javascript">
let DOM = document.getElementById('btn');
DOM.onclick = function(){
alert("click me")
}
</script>
三、使用事件监听绑定事件
事件绑定还有另一种方式,是使用addEventListener() 或者 attachEvent() 来进行事件绑定,也称为DOM2级事件绑定
1、addEventListener()
target.addEventListener(type, listener, options);
target:DOM操作获取的对象 type:事件类型的字符串('click','mouseenter','mousemove') listener:当监听的事件在该DOM上触发时,需要执行的函数 options:选填布尔类型的值。true是指让当前绑定的事件在捕获阶段执行;false指让当前绑定的事件方法在冒泡阶段时间。
<button id="btn">Click</button>
<script type="text/javascript">
let oBox = document.getElementById('btn');
oBox.addEventListener('click',func1);
oBox.addEventListener('click',func2);
function func1(){
alert("click me1!")
}
function func1(){
alert("click me2!")
}
</script>
2、attachEvent()
IE中的事件绑定。
<button id="btn">Click</button>
<script type="text/javascript">
let oBox = document.getElementById('btn');
oBox.attachEvent('onclick',func1);
oBox.attachEvent('onclick',func2);
function func1(){
alert("click me1!")
}
function func1(){
alert("click me2!")
}
</script>
使用attachEvent进行事件绑定,当事件触发,方法执行的时候,浏览器会把事件对象当做实参传递给函数。用这种方法绑定的对象是在冒泡阶段执行的。
四、DOM0级事件绑定和DOM2级事件绑定的区别
1、DOM0级事件绑定原理
1、给当前元素对象的某一个私有属性(onXXX)赋值的过程。(该属性的默认值都是null,赋值的过程就是给该事件绑定了一个方法) 2、当我们赋值成功后,浏览器会把DOM元素和赋值的函数建立关联,以及建立该DOM元素行为的监听,当行为触发,浏览器变会把相关行为赋值的函数执行。 3、只能给当前元素的某一个事件行为绑定一个方法,若进行多次绑定操作,最后一次绑定的方法会将之前的替换掉。
只有DOM元天生拥有的私有属性(onXXX),赋值的过程才叫做事件绑定
ducument.body.onclick = function(){} //事件绑定
document.body.onselly = function(){} //设置自定义属性
DOM0级事件移除方法
document.body.onclick = null
2、DMO2级事件绑定
1、DOM2事件绑定使用的addEventListener/attachEvent都是在EventTarget这个内置类的原型上定义的,我们调取使用的时候,首先通过原型链找到这个方法,然后执行完成事件绑定的效果。 2、浏览器首先会给当前元素的某一个事件行为开辟一个事件池(事件队列)[其实是浏览器有有一个统一的事件池,我们每个元素的某个行为绑定的方法都放在这个事件池中,只是通过不同的标识区分],当我们通过addEventListener做事件监听的时候,会把绑定的方法存放在事件池中。 3、当元素的某一个行为触发,浏览器会到事件池中把当前存放在事件池中的方法按照存放的先后顺序依次执行。
特点 1、所有DOM0支持的事件行为,DOM2都可以用;不仅如此,DOM2还支持一些DOM0没有的事件行为:DOMContentLoaded… 2、相对于DOM0来说,DOM2可以给当前元素的某一个事件行为绑定多个不同的方法(因为绑定的所有方法都存放在事件池中)
funcction f1(){
console.log(1);
}
funcction f1(){
console.log(2);
}
funcction f1(){
console.log(3);
}
document.body.addEventListener('click',f1,false);
document.body.addEventListener('click',f3,false);
document.body.addEventListener('click',f2,false);
document.body.addEventListener('click',f3,false);//本次向事件池中存储的时候发现f3已经在事件池中存在了,便不再进行存储
3、DOM2级事件的移除
document.body.addEventListener('click',f2,false);
document.body.removeEventListener('click',f2,false);