事件
js是由事件驱动的
浏览器会侦听页面,当我们出发了对应的行为(事件发生)执行对应的函数(事件的响应)
注册事件(绑定事件)
- 给元素添加事件,称为注册事件或者绑定事件
- 注册事件有两种方式:传统方式和方法监听注册方式
传统的注册方式
利用on 开头的事件onclick
内联JS
执行js代码
<button onclick="alert(hi~)"></button>
内联JS
执行函数(全局函数)
函数需要加括号
<div onclick ="fn()"></div>
function fn(){
alert("ok");
}
有参数的情况
<div onclick ="fn(1,2,event)"></div>
function fn(a, b ,e){
alert("ok");
}
DOM一级事件
var wrapBox = document.querySelector(".wrapBox");
wrapBox.onclick = function() {
alert('ok');
}
btn.onclick=function(){}
- 特点:注册事件的唯一性
- 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
方法监听注册方式 (DOM二级事件 )
w3c标准推荐方式
addEventListener() 它是一个方法
IE9之前的IE不支持此方法,可使用attachEvent()代替
特点:
- 同一个元素同一个事件可以注册多个监听器,绑定多个事件
- 可以自定义事件
事件监听可以有多个
按注册顺序依次执行
addEventListener 事件监听方式
https://www.runoob.com/jsref/met-element-addeventlistener.html
eventTarget.addEventListener(eventType,callback,useCapture)
eventTarget.addEventListener()方法将指定的监听器注册到eventtarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
该方法接收三个参数:
-
eventType( 必须参数) 事件类型字符串,必定带引号,比如click、mouseover,不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”
- 事件类型(click,dbclick,mousedown,keyup)
https://www.runoob.com/jsref/dom-obj-event.html
-
callback( 必须参数) 事件处理函数,事件发生时,会调用该监听函数。当事件对象会作为第一个参数传入函数。 事件对象的类型取决于特定的事件。例如, “click” 事件属于 MouseEvent(鼠标事件) 对象
-
useCapture (可选参数)是一个布尔值,指定事件是否在捕获或冒泡阶段执行
- true - 事件句柄在捕获阶段执行
- false- 默认 事件句柄在冒泡阶段执行
this指向绑定事件的元素
attachEvent 事件监听方式(IE9及其以下浏览器写法)
IE9之前版本支持
eventTarget.attachEvent()方法将指定的监听器注册到evenTarget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行。
该方法接收两个参数:
- eventNameWithOn:事件类型字符串,比如onclick、onmouseover,这里要带on
- callback:事件处理函数,当目标触发事件时回调函数被调用
注册事件 兼容处理
低版本IE存在兼容问题
自定义事件的触发(抛发)
抛发
// 先自定义事件
// 创建一个事件对象,honor为自定义的事件名
var e = new Event('honor');
console.log(e);
// 抛发
//由绑定事件的元素来抛发
// 传统的注册方式,也可以抛发
wrapBox.dispatchEvent(e)
创建鼠标。键盘的自定义事件对象
删除事件(解绑事件)
传统方式的解绑
内联JS 清除事件
删除对应事件的属性
一级事件 清除事件,设置为null
eventTarget.onclick=nul1;
方法监听方式的解绑
清除的时候的,对应函数名清除
函数触发谁,就指向谁,事件监听中的函数,绑定给谁,就指向谁
eventTarget.removeEventListener(eventType,function,useCapture);
// eventType 事件类型(click,dblclick ,mousedown,keyup)
// function 清除的函数
// bool是否在捕获阶段触发事件
//此时的function不能是匿名函数,必须在下面封装,在此处调用的的时候,不需要加括号
attachEvent事件的移除
eventTarget.detachEvent(eventNameWithon,callback);
删除事件兼容处理
事件传播的两种方式
历史渊源
网景浏览器 事件捕获 从最特定的元素到最特定的元素(由外而内)
IE浏览器 事件冒泡 从最特定的元素到最不特定的元素 (由内到外)
-
主流 事件冒泡
-
DOM 一级绑定 只能进行事件冒泡
-
低版本IE 只能冒泡
DOM事件流(父子元素都绑定同类型的事件)
- 事件流描述的是从页面中接收事件的顺序
- 事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
- 比如我们给一个div注册了点击事件:
DOM事件流分为3个阶段:
- 捕获阶段
- 事件由外而内触发一直找到事件源
- 当前目标阶段
- 如果目标元素(事件源)有事件,则先触发目标元素的事件
- 如果目标元素(事件源)没有事件,则进入冒泡阶段
- 冒泡阶段
- 自目标元素的父元素开始冒泡,如果有事件则会触发
- 事件冒泡:IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点的过程
- 事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程
形象理解
注意:
- js 代码中只能执行捕获或者冒泡其中的一个阶段
- onclick和attachEvent只能得到冒泡阶段
- addEventListener(type,listener,usecapture)
- 第三个参数如果是true,表示在事件捕获阶段调用事件处理程序;
- 如果是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
- 实际开发中我们很少使用事件捕获,我们更关注事件冒泡
- 有些事件是没有冒泡的,比如onblur、onfocus、onmouseenter、onmouseleave
- 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件
事件对象
- 事件对象事件发生时的所有相关信息(事件源(在谁身上触发的),事件类型(发生了什么事件)鼠标的位置及状态、按下的键,事件发生的时间)
- event 就是一个事件对象,写到我们侦听的函数的小括号里面,当形参来看
- 事件对象只有 有了事件才会存在,它是系统给我们自动创建的,不需要我们传递参数
- 事件对象 是 我们事件的一系列相关数据的集合,跟事件相关的,
- 比如鼠标点击,里面就包含了鼠标的相关信息,如鼠标坐标等。
- 如果是键盘事件,里面就包含的键盘事件的信息,比如判断用尸按下哪个键
- 这个事件对象我们可以自己命名,比如 event、evt、e
- 事件对象也有兼容性问题ie678,通过window.event获取
事件对象的使用语法
传统方式
addEventListener 方式
-
这个event 是个形参,系统帮我们设定为事件对象,不需要传递实参过去
-
当我们注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)
事件对象兼容性处理
事件对象本身的获取存在兼容问题:
-
标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到。
-
在IE6~8中,浏览器不会给方法传递参数,如果需要的话,需要到window.event中获取查找
-
解决:
e=e || window.event;
事件对象的通用属性
ctrlKey 事件触发时,ctrl键是否被按下
altkey 事件触发时,alt键是否被按下
shiftkey 事件触发时,shift键是否被按下
metakey 事件触发时,win键是否被按下
事件对象的属性
onmouseover/onmouseout 两个事件才有的属性
fromElement 事件触发时,从哪个元素来
toElement 事件触发时,到哪个元素去
事件对象的常见属性和方法
e.target属性 返回触发的事件对象
target 事件源 (触发事件的源头,由哪个元素触发的事件,绑定事件的元素本身,也有可能是它的子代元素)
srcElement 事件源(IE)
e.target 兼容性处理
e.currentTarget属性
跟this非常相似,但是IE 6 7 8不认识
e.target和this的区别
- e.target 返回的是触发事件的对象(元素),点击了那个元素,就返回哪个元素
- this 返回是是绑定事件的对象 (元素),哪个元素绑定了这个点击事件,那么就返回谁
e.type属性 返回事件的类型
事件类型是不带on的
浏览器默认行为
阻止 a标签的默认跳转
form的默认提交
阻止 按f5浏览器刷新
阻止 鼠标右键菜单
常规浏览器 e.preventDefault() 阻止默认行为(事件)
让链接不跳转或者让提交按钮不提交(DOM标准写法)
注意:
- 这是一个方法
- 别忘记加小括号
IE浏览器中 e.returnValue() 低版本浏览器,阻止默认行为
注意:
这是一个属性
兼容写法
addEventListener阻止默认行为
只有e.preventDefault一种方法
传统的注册方式,阻止默认行为
- 使用e.preventDefault()
- e.returnValue()
- 使用return false
- 也能阻止默认行为没有兼容性问题特点:return后面的代码不执行了,而且只限于传统的注册方式
阻止事件冒泡
事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点
事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握
- 由于事件传播的机制(事件冒泡),当父子元素绑定相同类型的事件,点击子元素会冒泡到父元素
- 当父子元素绑定不是相同类型的事件,则此处无法阻止事件冒泡
- 当父子元素绑定不是相同类型的事件,则各自走各自的完整的一套事件流
阻止事件冒泡的两种方式
- 标准写法:利用事件对象里面的stopPropagation()方法
- 阻止当前元素向父级冒泡
e.stopPropagation()
- 非标准写法:IE6-8利用事件对象cancelBubble属性
// e.cancelBubble默认为false
e.cancelBubble = true;
阻止事件冒泡兼容性解决
// 阻止冒泡的兼容写法
if(e.stopPropagation){
e.stopPropagation();
}
else{
e.cancelBubble = true;
}
事件委托
事件委托也称为事件代理,在jQuery里面称为事件委派
事件委托的原理
不要给每个子节点单独设置事件监听器,而是将事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
- 利用事件冒泡的原理,把子元素的事件委托给父代元素(页面中已经存在),由父代元素代为执行
优点:
-
节省内存
-
代码结构清晰
-
给未来生成的元素 绑定事件(页面加载的时候,没有生成,等待一定时间ajax,或则手动触发事件后新增)
-
可以用e.target 查看返回的是触发事件的对象(元素),点击了那个元素,就返回哪个元素
事件委托的作用
我们只操作了一次DOM,提高了程序的性能
利用冒泡特性,把子元素的事件,委托给父元素,查找元素
判断点击的元素,是什么类型的标签(按标签区分)
按类名区分
- 单类名
- 多类名
- 找下标
真数组才可以调用indexOf()方法
页面相关的事件
- window
- onload
- onresize
- onscroll
常用的鼠标事件
-
onclick 点击事件(鼠标左键)
-
ondbclick 双击事件
-
onmousedown 鼠标按下(左键 中键 右键均可触发)
- button值为0,则表示点击了左键
- button值为1,则表示点击了中键
- button值为2,则表示点击了右键
-
onmousemove 鼠标移动(每次都触发)
-
onmouseup 鼠标抬起
-
按下 移动 抬起 配合拖拽使用
-
onmouseover 滑入(只触发一次)
鼠标经过自身盒子会触发,经过子盒子还会触发。
- mouseenter 只会经过自身盒子触发,不会冒泡
-
onmouseout 滑出 (只触发一次)
问题
当鼠标滑到子元素上会先触发一次mouseout,再触发onmouseover
解决方法
用onmouseenter替换onmouseover
用onmouseleave替换onmouseout
contextmenu 禁止鼠标右键菜单
自定义右键菜单
selectstart禁止鼠标选中
鼠标事件对象
event对象代表事件的状态,跟事件相关的一系列信息的集合。现阶段我们主要是用鼠标事件对象MouseEvent 和键盘事件对象 KeyboardEvent
client 返回鼠标在可视区的x和y坐标(可视位置)
不管有没有滚动条,只返回当前可视区的坐标
page 返回鼠标在文档页面的x和y坐标(实际位置)
拖动滚动条的时候,返回滚动后的坐标
// 变相用于
pagex=clientx+document.documentElement.scrollLeft pageY=clientY+document.documentElement.scrollTop
screen 返回鼠标在电脑屏幕的x和y坐标
offset 事件触发时,鼠标相对于事件源的偏移
- 一旦出现元素嵌套,不能用此方法
图片跟随鼠标动
键盘事件
-
onkeydown 按键按下时触发事件(所有按键均可触发,虚拟键盘码(大小写 特殊字符和数字))
-
onkeyup 按键抬起/松开时触发事件
-
onkeypress 按键按下时触发(功能键不触发,文本输入的相关按键可以触发 数字 字母 标点符号 运算符)keycode按ASCII码来
注意
- 如果使用addEventListener****不需要加on
- onkeypress和前面2个的区别是,它不识别功能键,比如左右箭头,shift等。
三个事件的执行顺序是:keydown keypress keyup
两种绑定方式
- 绑定给document 文档的任何位置均可出发|
- 绑定给单行文本框或者多行文本域(input textarea 设置conteneditable了非表单元素)
键盘事件对象
keyup 和keydown
keyup 和keydown事件,不区分字母大小写,返回对应的keycode,a和A得到的都是65
keypress
区分字母大小写,返回对应的keycode
在onkeypress中,ctrl+enter
组合键的 keycode 为10
keycode
IE键盘码的兼容
var keycode=e.keycode || e.which;
通过ASCII码值,判断用户按下了哪个键
表单事件
onfocus 表单聚焦时触发
onblur 表单失焦时触发
onchange 表单内容改变时触发
- 有两个前提
- 内容改变
- 失去焦点(enter键也可以触发)
- 可在下拉框中使用,下拉框改变时触发(省市联动)
oninput 表单内容输入(即时输入)触发
onsubmit 表单提交
onsubmit 绑定给form 表单由提交(input,submit,button)按钮触发
阻止表单默认提交
表单重置
onreset 绑定给form表单,由重置(input:reset)触发
元素拖拽
- 拖拽的过程 按下 移动 抬起
- 鼠标按下onmousedown 记录鼠标按下的位置
-
鼠标移动onmousemove 相对于按下的位置移动
因为先按下才能移动所以两者是嵌套关系
- 最标抬起onmouseup 松开元素 不再移动