文章目录
dom事件
术语
-
事件:发生一件事
-
事件类型:发生什么事情;点击、鼠标按下、鼠标抬起、鼠标移入、鼠标移出、键盘按下、键盘抬起…
-
事件处理程序:一个函数,当某件事情发生时运行。
-
事件注册:将一个事件处理程序,挂载到某个事件上。
事件流
事件流:当某个事件发生的时候,哪些元素会监听到该事件发生,这些元素发生该事件的顺序.
当一个元素发生了某个事件时,那该元素的所有祖先元素(html结构上)都发生了该事件—这就是事件冒泡和事件捕获会发生的根本原因
事件冒泡:先触发最里层的元素,然后再依次触发外层元素
事件捕获:先触发外层的元素,然后再依次触发里面的元素
目前,标准规定,默认情况下,事件是冒泡的方式触发的;
事件源的祖先元素的事件默认发生在事件冒泡阶段;
事件源、事件目标:事件目标阶段的元素(事件触发的元素)
事件注册
事件绑定
dom0
将事件名称前面加上on,作为dom的属性名,给该属性添加一个函数,即为事件注册
移除:重新给事件属性赋值,通常为null、undefined
dom2
dom对象.addEventListner:注册事件
与dom0的区别
- dom2可以为某个元素的同一个事件,添加多个处理程序(按照事件注册顺序触发)
- dom2允许开发者控制事件处理的阶段,使用第三个参数,表示其是否在捕获阶段触发,默认为false,给事件目标写在捕获阶段触发无意义,只有给事件目标的父元素写才有意义
- 如果元素是目标元素(事件源),则第三个参数无效
事件的移除:dom对象.removeEventListner(事件名,处理函数-有名函数);
- 如果元素是目标元素(事件源),则第三个参数无效
dom2中如果要移除事件,不能使用匿名函数
细节:
- dom2在IE8及以下不兼容,需要使用attachEvent, detachEvent添加和移除事件,ie支持冒泡,所以没有第三个参数;
- 添加和移除事件时(removeEventListner),可以将第三个参数写为一个对象,进行相关配置
对象参数- capture:是否在捕获阶段运行
- once:该事件是否只运行一次
事件对象
封装了事件的相关信息
获取事件对象
- 通过事件处理函数的参数获取
ie的以前版本是window.event
事件对象的通用成员
- target属性 & srcElement属性
事件目标(事件源)
事件委托(给祖先元素注册事件,然后使用event.target判断事件源,进行不同的注册)
e.target.tagName 得到事件源的标签名
好处:使用事件委托注册的事件,动态添加子元素的时候事件也会被触发并且做出操作
通常,事件委托用于动态生成元素的区域
- currentTarget属性
当前目标:获取绑定事件的元素,等效于this
- type属性
字符串,得到事件的类型
- preventDefault方法 & returnValue属性
阻止浏览器默认行为-比如a元素有默认的行为跳转页面,button元素
e.preventDefault()–该方法可阻止浏览器的默认行为
e.returnValue属性是ie8以下的方法,但是现在这个已经建议不被使用–e.returnValue = false可以在ie8以下阻止浏览器默认行为
dom0的方式,在事件处理程序中返回false
针对a元素,可以设置功能性链接,阻止默认行为,在href属性中可以写’javascript:[void 0];’
void xxx—就是先运行xxx在返回undefined
- stopPropagation方法
阻止事件冒泡,在事件目标阶段阻止冒泡的话阻止后面的所有冒泡
写在冒泡阶段,该目标就是事件冒泡结束元素
- bubbles属性
布尔值,返回该元素的该事件是否冒泡
div.div1>p.div2>span.div3>button
div1.onclick = div3.onclick = button.onclick = function (e) {
console.log(e.currentTarget.tagName);
}
div2.onclick = function (e) {
e.stopPropagation();
}
// 只会打印span和button
- eventPhase属性
得到事件所处的阶段
1:表示事件捕获
2:表示事件目标
3:表示事件冒泡
鼠标事件
事件类型
-
click:用户按下主按钮(可以配置,一般是左键)或者在鼠标聚焦时按下回车;
-
dblclcik:用户双击主鼠标按键触发(频率取决于系统配置)–双击还会触发两次click事件
-
mousedown:用户鼠标按下的时候被触发
-
mouseup:用户抬起鼠标任意按键时触发
-
mousemove:鼠标在元素上移动时触发
-
mouseover:鼠标进入元素时触发
-
mouseout:鼠标离开元素时触发
先触发的时over和out,后出发enter和leave
- mouseenter:鼠标进入元素时触发,该事件不会冒泡-将子元素作为自己的一部分
- mouseleave:鼠标离开元素时触发,该事件不会冒泡
区别:
- over和out,不考虑子元素,从父元素移动到子元素,对于父元素而言,仍然算作离开
- enter和leave,考虑子元素,子元素仍然时父元素的一部分
- mouseenter和mouseleave
事件对象
所有的鼠标事件,事件处理程序中的事件对象,都为MouseEvent
下列为事件对象的属性
键盘判断
- altKey:触发事件时,是否按下了键盘的alt键
- ctrlKey:触发事件时,是否按下了键盘的ctrl键
- shiftKey:触发事件时,是否按下了键盘的shift键
- button:触发事件时,按下的鼠标类型(鼠标移入移出这样的事件不会触发)
- 0:左键
- 1:中键
- 2:右键
位置:
- page:pageX、pageY, 当前鼠标距离页面的横纵坐标
- client:clientX、clientY,鼠标相对于视口的坐标
- offset:offsetX、offsetY,鼠标相对于事件源的内边距的坐标
- screen:screenX、screenY,鼠标相对于屏幕
- x、y:等同于clientX、clientY
- movement:movementX、movementY,只在鼠标移动事件(mousemove)中有效,相对于上一次鼠标位置(并不是移动一个像素就触发)
window对象中有一个属性top,只可读不可写
- 使用movement
- 按前和按后的page差
- client
- 拖拽效果
- 仿照京东商城做放大镜
- 星星评分
键盘事件
注册事件尽量给大的元素注册事件,防止小元素无法聚焦导致无法触发键盘事件
事件类型
- keydown:按下键盘上任意键时触发,如果按住不放,会一直触发
- keypress:按下键盘上一个字符键时触发
- keyup:抬起键盘上任意键触发
keydown和keypress如果阻止了默认行为,文本不会显示
press:往往有点反馈
input框能够将输入的字符显示是因为keydown、keypress的默认行为,只需要阻止其中一个事件中的默认行为就无法输入字符;
事件对象
KeyboardEvent
大部分已经过期
-
keycode、which:得到键盘编码
-
code属性:得到按键字符串,适配键盘布局(可以识别左右)。
-
key属性:得到按键字符串,不适配键盘布局;能得到打印字符
其他事件
聚焦事件(表单事件,a元素)
- focus:元素聚焦的时候触发(能与用户发生交互的元素,都可以聚焦),该事件不会冒泡
- blur:元素失去焦点时触发,该事件不会冒泡
- submit:提交表单事件,仅在form元素有效,提交的是整个表单,该事件可以冒泡
- change:文本改变事件, 离开文本框的时候触发
- input:文本改变事件,即时触发–可以用来做即使验证,该事件无法阻止默认行为
输入框有一个defaultValue的属性—值是一开始在html元素行间写的value的值
其他事件
window全局对象
- load、DOMContentLoaded、readystatechange
window的load:页面中所有资源加载完毕的事件
图片dom的load:图片异步加载完成之后触发的事件–这种场景应用较多
浏览器渲染页面的过程
- 得到页面源代码
- 创建document节点
- 从上到下依次执行代码
- 将元素依次添加到dom树中,每添加一个元素,进行预渲染
有外部资源的时候进行同步加载外部资源
asynchronous
async–布尔属性,写在行间表示该资源异步加载
sync–同步的
js代码应该尽量写到页面底部,先看到页面,在看到功能,而且js同步加载很浪费时间
document的DOMContentLoaded:dom元素构建完成之后发生-该事件必须使用dom2的注册方法
readystate:loading、interactive(dom已经建立好了)、complete
interactive:触发DOMContentloaded事件
complete:触发window的load事件
document.readystate;
window.addEventListner('DOMContentloaded', function () {
console.log(document.reaystate);
});
window.addEventListner('load', function (){
console.log(document.readystate);
})
// 输出顺序是loading、interactive、complete
document.readystatechange事件:当页面状态发生改变后触发该事件
-
css代码应该写到页面底部:避免出现闪烁(如果放到页面底部,会导致元素先没有样式,会使用丑陋的默认样式,然后到读到css文件后,重新改变样式)
-
js应该写到页面底部:避免阻塞后续的渲染,也避免运行js时,得不到页面中的元素。
-
unload、beforeunload
beforeunload:window的事件,关闭窗口时运行,可以阻止关闭窗口(在事件处理函数中返回一个字符串即可)
unload:window的事件,关闭窗口时运行
- scroll
窗口发生滚动时运行的事件,触发频率无法自己决定,取决于配置和浏览器
通过scrollTop和scrollLeft,可以获取和设置滚动距离
细节:如何获取整个网页的滚动条top和left
-
document.documentElement.scrollTop + document.body.scrollTop,这两个值一个一定是0, 一个是有值的,所以相加可得最终值.
-
resize
window的事件
窗口尺寸发生改变后运行的事件,监听的是可视区的尺寸
- window的属性
- window.innerWidth、window.innerHeight
窗口的内尺寸(包含滚动条) - window.outerWidth、window.outerHeight
窗口的外尺寸 - document.documentElement.clientWidth、document.documentElement.clientHeight
得到视口尺寸(不包含滚动条) - window.screen.width、window.screen.height—客户的屏幕尺寸
-
dom的属性
dom.clientWidth、dom.clientHeight—不包含边框和滚动条
dom.offsetWidth、dom.offsetHeight—包含边框和滚动条
dom.scrollWidth、dom.scrollHeight—包含所有实际的内容(包括不可见的区域),不包含滚动条和边框 -
contextmenu
右键菜单事件,阻止默认行为的话就不可以通过点击右键来使得无法出现菜单事件
- paste
粘贴后触发的事件,阻止默认行为的话无法粘贴
window.clipboardData || e.clipboardData – 在paste事件中可得到一个对象obj, obj.getData(‘MIME’)可得到字符串,obj.setData(‘MIME’, data)—这个方法现在无法使用,obj.clearData(‘MIME’)—清空文本框;
MIME-互联网中字符串的标准格式
- text/plain—普通文本
-
copy
复制元素内容后触发的事件,阻止默认行为的话无法复制 -
cut
剪切后触发的事件,阻止默认行为后无法进行剪切
补充知识
元素位置
每个元素都有的属性
- offsetParent
获取某个元素的第一个有定位的父元素,如果没有,则得到body
body的offsetParen是null
- offsetLeft、offsetTop
相对于该元素的offsetParent的坐标
如果该元素的offsetParent是body,则将其当作是整个网页
注意这里的right值是指视口左部到元素右端的距离
- getBoundingClientRect
该方法得到一个对象,该对象记录了该元素相对于视口的距离
事件模拟
- click
先绑定事件,然后直接调用就可以手触发
dom.click(); - submit
只有以上两个事件才可以这样直接调用
其他事件需要使用到dispatchEvent触发
- dispatchEvent方法
dom.dispatchEvent(event);—这个实参event可以是用MouseEvent构造函数new出来的对象
var event = new MouseEvent("mouseenter", {
bubbles:false
// 一些配置
})
其他补充
- window.scrollX、window.pageXOffset、window.scrollY、window.pageYoffset
window.scrollX、window.pageXOffset:相当于根元素的scrollLeft
window.scrollY、window.pageYOffset:相当于根元素的scrollTop
-
scrollTo(x, y)、scrollBy(offsetX, offsetY)
window的方法
scrollTo设置滚动条的位置
scrollBy是基于原来位置改变 -
resizeTo(width, height)、resizeBy(offsetWidth, offsetHeight)
window的属性,这个方法只能是用代码打开的窗口才可以设置,用户的浏览器窗口不允许设置