1.如何注册事件(如何绑定事件)
何为注册事件,就是给元素添加事件,其方式有传统注册事件、方法监听注册事件。
-
0、1级事件(传统注册事件)不允许多个响应程序
我们在元素内或js内使用on的方式就是传统注册事件,这种形式添加的事件叫DOM 0级事件(DOM L0 事件),如onclick、onblur等
<div id="box" onclick="fn()"></div> <script> // js里面也可以注册事件 let box = document.getElementById("box") box.onclick = function (){ console.log("注册click事件成功1") } box.onclick = function (){ console.log("注册click事件成功2") } //这里只会打印"注册click事件成功2" ,因为不允许多个响应程序,后面会覆盖前面的事件 </script>
-
2级事件(方法监听注册事件)允许多个响应程序,事件触发时依次调用
-
方法1:元素.addEventListener:
// IE9之前的IE不支持此方法 元素.addEventListener('事件名', 事件响应程序(函数)callback,useCapture) // useCapture:可选参数,是一个布尔值,默认是 false // true 是捕获阶段 false是冒泡阶段 事件触发会依据事件流的顺序调用 // 例如以下 box.addEventListener('click', function () { // 给box添加点击事件 }) // 允许多个响应程序,事件触发时依次调用 box.addEventListener('click', function () { console.log('1') }) box.addEventListener('click', function () { console.log('2') }) //这里会依次打印1、2
-
方法2:元素.attachEvent( on事件名, 响应程序 )
// IE9之前的浏览器支持 元素.attachEvent( on事件名, 事件响应程序(函数)callback ) box.attachEvent('onclick', function () {})
2.如何删除事件(如何解除绑定事件)
用哪种方式添加的事件,我们只能用对应方式来删除,无法混用,而且要注意是否注册的是匿名函数,这种事件无法删除。
-
0、1级事件的删除方法:
元素.on事件名 = null 或者 = undefined box.onclick = null 或者 box.onclick = undefined
-
2级事件的删除方法:
addEventListener的删除:
元素.removeEventListener('事件名', 函数名) // 匿名函数例子 box.addEventListener('click', function () { console.log('1') }) // 非匿名 function fn(){} box.addEventListener('click', fn) // 删除例子 box.removeEventListener('click',fn)
attachEvent的删除
元素.detachEvent('on事件名', 函数名)
3.什么是DOM事件流
-
事件流:当一个事件触发后,它其实经历了从上(捕获阶段)到下(事件目标),又从下(事件目标)到上(冒泡阶段)的流动过程,这就称之为事件流
-
事件冒泡默认存在的,事件捕获要写特殊代码才能看到,如下。
- 例如:addEventListener的第三个参数写为true就是事件捕获,所以前面写的addEventListener里面提到的就是这里
-
不管是捕获、冒泡,都会触发同名事件
-
事件流如果不写特殊代码,会经历完整的事件流。
<div id="div1" style="background: blue;width: 100px; height: 100px;"> <div id="div2" style="background: red;width: 70px; height: 70px;"> <div id="div3" style="background: yellow;width: 50px; height: 50px;"></div> </div> </div> <script type="text/javascript"> var oDiv1 = document.getElementById('div1'), oDiv2 = document.getElementById('div2'), oDiv3 = document.getElementById('div3'); oDiv1.addEventListener('click', showBlue, true); oDiv2.addEventListener('click', showRed, false); oDiv3.addEventListener('click', showYellow, true); function showBlue(){ //蓝 alert("blue");} function showRed(){ //红 alert("red"); } function showYellow(){//黄 alert("yellow");} // 结果“blue”,“yellow”,“red” // true 是捕获阶段,依据事件流是先执行,所以先出蓝 黄,false是冒泡阶段,所以最后出红 </script>
-
4.什么是事件对象
事件对象也是一个对象,里面保存了事件触发时的相关信息,event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
比如:键盘触发的事件,会得到键盘相关信息,如enter键
-
怎么获取事件对象?
- 如事件绑定的函数里写一个形参event/e、或者写window.event
-
事件对象的兼容性方案(IE6~8 和IE8之后都可以使用)?
- e = e || window.event
eventTarget.onclick = function(event) { // 这个 event 就是事件对象} eventTarget.addEventListener('click', function(event) { }) // 形参是可变的,随便起名字,但一般用event、e、ev
-
怎么获取事件源?
事件对象.target || e.target
是我们事件触发的元素,比如我点body就是body,我点div就点的那个div;this
当前事件调用函数的绑定元素,this是注册当前事件的父元素;
事件对象常见的属性方法 | 说明 |
---|---|
e.targer | 返回触发事件的对象 标准 |
e.type | 返回事件的类型 比如click mouseover 不带on |
e.cancelBubble | 该属性阻止冒泡 非标准 ie6-8使用 |
e.returnValue | 该属性阻止默认事件(默认行为) 非标准 ie6-8使用 比如不让链接跳转 |
e.preventDafault() 阻止事件默认行为 | 该方法阻止默认事件(默认行为) 标准 比如不让(a标签)链接跳转 |
e.stopPropagation() | 阻止冒泡标准,当父子有同名事件,为了不相互影响时可以使用 |
e.currentTarget | 与this一样,非标准 ie6-8使用 |
5.阻止事件冒泡、事件捕获(阻止事件流)
- e.stopPropagation() (IE9后支持)
- 可以阻止冒泡、捕获阶段
- e.cancelBubble = true(IE9前支持)
- IE9之前没有事件捕获(因为IE9之前无法用addEventListener)
// 兼容性解决方案
box.addEventListener('click', function(e) {
alert('box');
// 兼容性写法
if (e && e.stopPropagation) {
e.stopPropagation(); //适用于ie9后
} else {
window.event.cancelBubble = true; // 适用于ie678
}
}, false);
工作实际案例场景:
1、登录页面,登录弹出框与后面父元素背景的点击事件冲突时;
2、移动端,某个弹出框,不希望点击到阴影部分的功能;
3、拓扑页面存在点击事件,需要在上层弹出某个弹框,可以拖拽改变页面大小;
6.事件委托(事件代理、事件委派)
把给每个子元素单独设置事件监听器的需求,改成事件监听器设置在其父元素上,利用冒泡原理代理到子元素上。
-
好处:减少绑定事件的次数,提高性能(只操作了一次 DOM ,提高了程序的性能),减少代码冗余,即使新增的子元素也享有事件监听器;
-
需求:给li添加点击事件,并且获得里面的key值
解决办法1:给每个li添加点击事件,这种方法代码太过冗余
优化解决办法:把事件委托给ul元素,给它添加点击事件方法,利用事件冒泡
-
<ul> <li key="1">点我点我宝贝</li> <li key="2">点我点我宝贝</li> <li key="3">点我点我宝贝</li> <li key="4">点我点我宝贝</li> <li key="5">点我点我宝贝</li> <span key="6">不是li</span> <span key="7">不是li</span> </ul> <script> let ul = document.querySelector('ul'); ul.addEventListener('click',function(e){ if(e.target.tagName === 'LI'){ // 判断是不是li标签 return e.target.getAttribute('key') }}) </script>
7.常用的事件
①鼠标事件
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获取鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
contextmenu | 鼠标右键触发(e.preventDefault() 阻止弹出右键菜单,场景:取消默认的上下文菜单,加入自己的菜单;复制网页内容功能屏蔽) |
selectstart | 鼠标选择开始(e.preventDefault() ;场景:复制网页内容功能屏蔽,禁止用户选中) |
MouseEvent鼠标事件对象 | 说明(像素距离) |
---|---|
e.clientX | 鼠标相对于浏览器窗口可视区的X坐标(变) |
e.clientY | 鼠标相对于浏览器窗口可视区的Y坐标(变) |
e.pageX | 鼠标相对于页面的X坐标 IE9+支持(doc) |
e.pageY | 鼠标相对于页面的Y坐标 IE9+支持(doc) |
e.screenX | 鼠标相对于电脑屏幕的X坐标 |
e.screenY | 鼠标相对于电脑屏幕的Y坐标 |
②键盘事件
使用addEventListener 不需要加 on
键盘事件 | 触发条件 |
---|---|
onkeydown/keydown | 按下时触发,不区分大小写字母,任何键 |
onkeyup/keyup | 松开时触发,不区分大小写字母,任何键 |
onkeypress/keypress | 按下时触发,介于 keydown 和 keyup之间,(a-z0-9回车和空格),会区分大小写,不识别功能键 |
键盘事件对象 | 说明 |
---|---|
keyCode | 返回该键的ASCII值 |