JS-事件
事件绑定
DOM 0级事件
有2个:HTML标签中事件和元素.on事件=函数
HTML标签中事件
<a href="#" onclick="open()">打开</a>
元素.on事件
var btn = document.getElementById("btn1");
btn.onclick=function(){
console.log("sj1");
}
btn.onclick=function(){ //会覆盖原来的函数
console.log("sj2");
}
这种方法只能触发一个函数,若要触发多个可以用addEventListener
DOM 1级事件
只有一个:addEventListener()
IE 678不支持
addEventListener
addEventListener可以给一个对象添加多个触发函数
addEventListener(event,function,<useCapture>);
- 参数1:String类型,事件名
- 参数2:执行的函数
- 参数3:是否在捕获阶段触发执行,默认false(冒泡时触发)
参数3解析:一个事件触发的流程是 触发事件 -> 捕获过程 -> 冒泡过程
DOM事件流
d3包含在d2,d2包含在d1;点击d1,产生以下结果:
事件冒泡
//若都是冒泡阶段触发,则执行顺序为:d3,d2,d1(从里向外冒泡)
d1.addEventListener('click',say);
d2.addEventListener('click',say);
d3.addEventListener('click',say);
事件捕获
//若都是捕获阶段触发,则执行顺序为:d1,d2,d3(从外向里)
d1.addEventListener('click',say,true);
d2.addEventListener('click',say,true);
d3.addEventListener('click',say,true);
混合:
//由内向外依次检测是否有捕获过程执行的,然后冒泡
//若一部分是冒泡,一部分是捕获,则先从外向里执行捕获,再从里向外执行冒泡
d1.addEventListener('click',say,true);
d2.addEventListener('click',say);
d3.addEventListener('click',say);
图(摘自:qianguyihao)
不冒泡事件
有:blur、focus、load、unload、onmouseenter、onmouseleave
例:
d1.addEventListener('mouseenter',say);
d2.addEventListener('mouseenter',say);
d3.addEventListener('mouseenter',say);
document.body.addEventListener('mouseenter',say);
document.addEventListener('mouseenter',say);
鼠标移入body,结果为:body
鼠标移入d1,结果为:d1
鼠标移入d2,结果为:d2
…
鼠标直接移入d3,结果为:body,d1,d2,d3
document的事件没有被触发,因为该事件不会冒泡
直接移入d3产生了"类似冒泡",是因为其他元素真实产生了事件,然后按事件捕获由外由内执行
若是click事件,则无论任何时候,都会产生冒泡
总结:不冒泡的事件,例如load时每个元素如果都冒泡的话就没有意义了
阻止冒泡
IE,谷歌,火狐:event.stopPropagation()
IE,谷歌:event.cancelBubble = true
例:
//点击d3,结果只有d3,没有冒泡到父级
d1.addEventListener('click',say);
d2.addEventListener('click',say);
d3.addEventListener('click',say);
function say(){
//兼容性代码
event=event | window.event;
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble=true;
}
......
}
removeEventListener
removeEventListener(event,function,<useCapture>);
常用事件
addEventListener中使用不用加on,DOM 0级事件要加on
鼠标事件
事件名 | 解释 |
---|---|
onclick | 单击 |
ondblclick | 双击(不要漏了l) |
onmousedown | 鼠标按下 |
onmouseup | 鼠标松开 |
onmousemove | 每次移动都触发 |
onmouseenter | 当次进入时仅触发一次 |
onmouseleave | 当次离开时仅触发一次 |
onmouseover | 当次进入时触发一次,若触碰到子元素并再次回到该元素(并不出界)时会再次触发 |
onmouseout | 离开,进入子元素,进入子元素并回到当前元素,进入子元素的子元素的子…都会触发 |
oncontextmenu | 在当前元素上右击打开菜单时触发(只要弹出菜单就触发,不是必须右键) |
键盘事件
事件名 | 解释 |
---|---|
onkeydown | 按下任意键(按下不松开会一直触发) |
onkeyup | 松开任意键 |
onkeypress | 按下任意键(按下不松开会一直触发)(和keydown相比,按下altctrlf1-f10等键时keypress不会触发) |
其他事件
事件名 | 解释 |
---|---|
onload | 一般用于window.onload,页面加载完后执行某些代码 |
onchange | 例如文本框内容改变时触发 |
event对象
不同浏览器写法(例如window.event/event)和值(例如button属性)不同,可能存在兼容性问题
在触发一个事件时,会产生一个event对象,如下:
d1.addEventListener('mousedown',say);
function say(){
console.log(event); //产生event对象
}
常见属性
属性名 | 解释 |
---|---|
timeStamp | 触发时间(ms) |
target | 事件源 |
button | 鼠标按键 谷歌,IE9+,火狐(左0 ,中1 ,右2 ) IE678(左1 ,中4 ,右2 ) |
pageX/pageY | 光标在页面中的位置(px),例如页面左上角pageX=0,pageY=0 |
clientX/clientY | 光标在页面中相对于可视区域(滚动条外的区域不算)的位置(px) |
事件委托
有一个列表:
<ul id="ul">
<li id="li1">li1</li>
<li id="li2">li2</li>
<li id="li3">li3</li>
</ul>
要实现点击li,输出id,正常情况下要分别添加3个li的事件,实际上可以利用冒泡原理,在父元素ul中添加li的事件来实现
实现代码:
ul.addEventListener('click',say);
function say(){
if(event.target.nodeName.toUpperCase()=="LI"){ //判断事件源节点名是不是LI
console.log(event.target.id); //如果是就输出事件源的id
}
}
点击li,虽然li没添加事件,但冒泡到父元素ul时,父元素运行事件代码
利用事件委托可以节省内存,提高效率