在这里整理一下js中事件包含的各种知识。
参考资料:
事件句柄(Event Handlers)
- onabort: 图像加载被中断
- onblur:元素失去焦点
- onchange:用户改变域的内容
- onclick:鼠标点击某个对象
- ondblclick:鼠标双击某个对象
- onerror:当家在文档或图像时发生某个错误
- onfocus:元素获得焦点
- onkeydown:某个键盘的键按下
- onkeypress:某个键盘的件被按下或按住(长按)
- onkeyup:某个键盘的键被松开
- onload:某个页面或图像被加载完成
- onmousedown:某个鼠标按键被按下
- onmouseover:鼠标被移动
- onmouseout鼠标从某元素上移开
- onmouseover:鼠标被移到某元素之上
- onmouseup:某个鼠标按键被松开
- onreset:重置按钮被点击
<button type="reset" value="Reset">Reset</button>
- onresize:窗口或框架被调整尺寸
- onselect:文本被选定
- onsubmit:提交按钮被点击
<button type="submit" value="Submit">Submit</button>
- onunload:用户退出页面
Event事件对象的属性
- altKey:返回布尔值,表示当事件被触发时,“ALT”是否按下
- bubbles:返回布尔值,表示事件是否是起泡事件类型。
- button:返回当事件被触发时,哪个鼠标按钮被点击
- cancelable:返回布尔值,表示时间是否可用preventDefault()取消默认动作
- char:
- charCode:
- ctrlKey:返回布尔值,表示事件触发时,“CTRL”键是否按下
- currentTarget:返回其事件监听你过去触发该事件的元素
- target:返回出发此事件的元素(事件的目标节点)。
- relatedTarget:返回与实践的目标节点相关的节点
- eventPhase:返回事件传播的当前阶段。1.捕获阶段2.正常事件派发3.起泡阶段
- keyCode:被敲击的键盘按键的Unicode码
- metaKey:返回布尔值,表示当事件被触发时,“meta”是否按下
- shiftKey:返回布尔值,表示当事件被触发时,“SHIFT”是否按下
- timeStamp:返回时间生成的日期和时间
- type:返回字符串,表示当前Event对象表示的事件的名称
- screenX:返回事件触发时,鼠标指针的水平坐标
- screenY:返回事件触发时,鼠标指针的垂直坐标
- clientX:返回事件触发时,鼠标指针的水平位置
注意:target/currentTarget/relatedTarget之间的区别。
target返回触发事件的元素。currentTarget始终返回绑定事件的元素。
在下面的例子中,target返回点击的元素,可能返回a,li,ul。但是currentTarget永远返回绑定事件的元素,也就是ul。这个返回的ul,也就是event中的this。
例子:
<ul id="ul">ul
<li>li<a href="">a</a></li>
<li>li<a href="">a</a></li>
<li>li<a href="">a</a></li>
</ul>
<script>
var ul = document.getElementById("ul");
ul.onclick = function(event){
var tar = event.target;
var curtar = event.currentTarget;
var tagName = tar.nodeName.toLowerCase();
console.log("你点击了:"+tagName);
console.log(curtar == this);
event.preventDefault();
}
</script>
relatedTarget属性返回的是与事件目标节点相关的节点。只对mouseover和mouseout事件有用,对其他事件,这个属性没有用。
对mouseover事件来说,该属性是鼠标指针移到目标节点上时,所离开的那个节点
对mouseout事件来说,该属性是鼠标指针离开目标时,所进入的那个节点。
注意:各种X,Y之间的区别。
event.clientX、event.clientY
鼠标相对于浏览器窗口可视区域的X,Y坐标(窗口坐标),可视区域不包括工具栏和滚动条。IE事件和标准事件都定义了这2个属性
event.pageX、event.pageY
类似于event.clientX、event.clientY,但它们使用的是文档坐标而非窗口坐标。这2个属性不是标准属性,但得到了广泛支持。IE事件中没有这2个属性。
event.offsetX、event.offsetY
鼠标相对于事件源元素(srcElement)的X,Y坐标,只有IE事件有这2个属性,标准事件没有对应的属性。
event.screenX、event.screenY
鼠标相对于用户显示器屏幕左上角的X,Y坐标。标准事件和IE事件都定义了这2个属性
Event方法
事件流
当浏览器发展到第四代时(IE4和Netscape Communicator 4),浏览器团队遇到一个很有意思的问题:页面的哪一部分会拥有特定的事件?想象下在一张纸上有一组同心圆,如果你把手指放在圆心上,那么你的手指指向的不是一个圆,而是一组圆。两家公司的开发团队在看待浏览器事件方面还是一致的。如果你单击了某个按钮,那么同时你也单击了按钮的容器元素,甚至整个页面。
事件流描述的是从页面中接受事件的顺序。但有意思的是,IE和Netscape开发团队居然提出了两个截然相反的事件流概念。
IE的事件流是 事件冒泡流;标准的浏览器事件流是 事件捕获流。不过addEventLister给出了第三个参数同时支持冒泡与捕获,下文将介绍。
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。首先发生的事件捕获,为截获事件提供机会。然后是实际的目标接受事件。最后一个阶段是时间冒泡阶段,可以在这个阶段对事件做出响应。多数支持DOM事件流的浏览器都实现了一种特定的行为;即使“DOM2级事件”规范明确要求捕获阶段不会涉及事件目标,但IE9、Safari、Chrome、Firefox和Opera9.5及更高版本都会在捕获阶段触发事件对象上的事件。结果,就是有两个机会在目标对象上操作事件。
为了最大限度的兼容,大多是情况下都是将事件处理程序添加到事件冒泡阶段。不是特别需要,不建议在事件捕获阶段注册事件处理程序
事件冒泡
ie 的事件流叫事件冒泡,也就是说事件的传播为:从事件开始的具体元素,一级级往上传播到较为不具体的节点。现代浏览器都支持事件冒泡,IE9、Firefox、Chrome和Safari则将事件一直冒泡到window对象。如:
<p>--<div>--<body>--<html>--<window>
事件捕获
Netscape团队提出的另一种事件流叫做事件捕获。它的原理刚好和事件冒泡相反,它的用意在于在事件到达预定目标之前捕获它,而最具体的节点应该是最后才接收到事件的。如
<window>--<html>--<body>--<div>--<p>
IE9、Firefox、Chrome和Safari目前也支持这种事件流模型,但是有些老版本的浏览器不支持,所以很少人使用事件捕获,而是用事件冒泡的多一点。
事件处理程序
上边说了浏览器的各种事件,遇到事件要执行的就是事件处理程序。DOM2提供了两个方法来让我们对其进行操作: addEventListener()和removeEventListener()
dom.addEventListener(eventType,function(){},false)
//dom为该方法应用的dom节点
//eventType为事件名
//function为事件处理程序
//第三个为布尔值,true为事件捕获阶段调用事件处理程序,false为事件冒泡阶段调用事件处理程序
//所以我们默认添加的事件,都是在冒泡阶段调用的。
事件代理/事件委托
事件代理/事件委托之前写过了,是事件的一个非常简单的应用方式,他俩是同一个东西,不同的名字而已。
如果我们给多个元素(如li)绑定同一个方法,可以直接利用事件冒泡,将方法绑在他们的父元素(如ul)上,然后使用e.target即可得到相应的子元素(li)。
这样既简化了逻辑,也节省内存,提高性能。
事件的防抖与节流
有时我们希望一些事件如scroll,resize,keyup等多次触发,但如果过于频繁,会导致界面卡顿,甚至浏览器崩溃。为了不影响性能,又需要限制他的触发频率,这时候就需要使用函数节流(throttle)和函数防抖(debounce)来解决这个问题。
函数节流(throttle)和函数防抖(debounce)都是通过延时逻辑操作来提升性能的方法,在前端优化中是常见且重要的解决方式。可以从概念和实际应用中理解两者的区别,在需要的时候选择合适的方法处理。
函数节流(throttle)
函数节流就是预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。好像水滴攒到一定重量才会落下一样。
场景:窗口调整(resize);页面滚动(scroll);抢购疯狂点击(mousedown)
实现:函数节流与函数防抖
函数防抖(debounce)
函数防抖就是在函数需要频繁触发情况时,只有足够空闲的时间,才执行一次。好像公交司机会等人都上车后才出站一样。
场景:实时搜索(keyup);拖拽(mousemove)
实现:函数节流与函数防抖