注册事件
前面学习到注册事件方法如下
<button onclick="alert("hi")">注册事件</button>
btn.onclick=fuction(){}
但是这样注册事件有一个缺点,同一个元素不能注册两个事件,前面的事件会被后面的事件覆盖掉。
监听注册事件 addEventListener
evenTarget.addEventListener(type,listener[,useCapture])
- type :事件类型的字符串 'click', 'mouseover' ,注意不带 on
- listener 事件处理函数
useCapture
,可选值 默认为false
实例:
var btn=document.querySelector('button');
btn.addEventListener('click',function(){
alert('监听注册事件');
});
使用这个方法,一个元素就可以加入不同事件了。IE9之前不支持。
删除事件 removeEventListener
如果我们采用btn.onclick=fuction(){}
的方法,那么我们想要删除,其实只需要,btn.onclick=null
就好了。
如果采用后面的方法
target.removeEventListener(type, listener[, options]);
- type,一个字符串,表示需要移除的事件类型,如
"click"
。 - listener: 需要移除的函数名
当然如果前面你写的是匿名函数,就无法通过这个方法解绑了。
var btn=document.querySelector('button');
btn.addEventListener('click',fn);
function fn(){
alert('监听注册事件');
//移除事件
btn.removeEventListener('click',fn)
}
dom 事件流
事件流就是 从页面接受事件的顺序;
事件发生时会在元素节点之间,按照特定的顺序传播,这个传播的过程就叫做事件流
如上图我们给div注册了个事件,当事件触发的时候并不是div直接执行事件函数的,而是经历如上图流程。
- 捕获阶段:事件由页面元素接收,逐级向下,到具体的元素
- 目标阶段: 目标元素执行阶段
- 冒泡阶段:跟捕获相反,具体元素本身,逐级向上,到页面元素
比如div注册了个click事件,先从 document一步步捕获,找到谁是click的目标,看到document没有click事件就去找他的子元素html,发现html也没有,在一步一步找到div。这就好像事件click在被传播,所以才叫事件流。
另外,如果捕获,冒泡,同时存在,如图那么先走捕获,在走冒泡
开始论证
evenTarget.addEventListener(type,listener[,useCapture])
,我前面对这个 第三个参数没有过多的介绍,其实放在这里才能说的清楚。
useCapture
,可选值 默认为false
- 如果true,表示在走捕获阶段调用处理事件函数
- 默认,false,那么就表示冒泡了。

捕获阶段
根据前面粗略的讲解,我们可以大胆猜测,捕获阶段,父元素如果和子元素有相同的条件触发,那么父元素会比子元素先执行。
var son=document.querySelector('.son');
var father= son.parentNode;
son.addEventListener('click',function(){
alert('子元素后执行');
},true);
father.addEventListener('click', function () {
alert('父元素元素先执行');
}, true);
事实的确如此。

冒泡阶段
那么就和前面的相反即可。父元素如果和子元素有相同的条件触发,那么子元素会比父元素先执行。
捕获冒泡同时存在
同时存在的话,那么先捕获后冒泡。
var son=document.querySelector('.son');
var father= son.parentNode;
son.addEventListener('click',function(){
alert('子元素 ');
},true);
father.addEventListener('click', function () {
alert('父元素 冒泡');
}, false);
father.addEventListener('click', function () {
alert('父元素 捕获');
}, true);

事件对象 event
我们的事件处理函数,也是有参数的,
btn.onclick=fuction(event){}
,我们可以从event获取很多关于事件的信息,鼠标的坐标,按键的asc码等等。
当然只要事件处理函数,有了参数,我们就可以从中获取信息,不一定要event才可以,写作 e也可以。
万恶的ie 6 7 8版本是通过 只能写window.event
,为了兼容性我们可以这样写
btn.onclick=fuction(e){ e=e||window.event;}
通过逻辑短路来处理。
e.target
返回触发事件对象。
我们在这里要分开,this和target
this返回的是绑定事件的对象。
target 返回的触发对象。
比如如下情况
<div>target
<span>this</span>
</div>
<script>
var div =document.querySelector('div');
div.addEventListener('click',fn);
function fn(e){
console.log(e.target);
console.log(this);
}
</script>
span是 div的子元素,当我们点击,span里的target 文字,
e.target返回的是span, this返回的是 div。
e.type
返回事件类型
比如 click,mouseover; 不带on!
preventDefault()
阻止默认的行为
我们可以通过这个方法,实现让链接不跳转
<a href="https://yingwiki.top">点我不会跳转</a>
var a=document.querySelector('a');
a.addEventListener('click',function(e){
e.preventDefault();
})
这个函数在老ie是没有的,还有一个方法也可以实现一样的效果。
使用 btn.onclick=fuction(event){}
注册事件
rerurn false;
也可以实现不跳转,但是return 后面的代码就不会执行。
如何阻止冒泡
我们常用的冒泡来触发事件,为了保证父元素和子元素有一样的触发事件的时候,我们不想要的画面。阻止冒泡是必不可少的。
e.stopPropagation();
我们给事件处理函数加上这一句就可以了。
当然为了兼容ie,我们可以这样写
if(e&&e.stopPropagation)
{
e.stopPropagation();
}else{
//ie支持这样子的
window.event.cancelBubble=true;
}
事件委托
当然事件冒泡不一定只有坏处,灵活执行还有不少的好处。
<ul>
<li>事件委托</li>
<li>事件委托</li>
<li>事件委托</li>
<li>事件委托</li>
<li>事件委托</li>
</ul>
如果我们想每个li 都有点击事件,我们可以使用循环去注册事件,但是这样也会有坏处,访问do次数太多,效率不高。
想这个情况,我们就可以给父元素ul注册点击事件,利用target获取每个li,我们这里改变我们点击li的背景颜色
var ul=document.querySelector('ul');
ul.addEventListener('click',function(e){
for(var i=0;i< ul.children.length;i++)
{
//还原其他li的背景颜色
ul.children[i].style.backgroundColor='#fff';
}
e.target.style.backgroundColor='#999';
});
鼠标事件对象 MoseEvent
常用属性说明
e.clentX,e.clentX
相对可视区的坐标。
这个坐标是不随着页面的滚动而随意改变的。
pageX ,pageY
相对于整个文档的坐标,滚动条往下滚坐标也会改变。
screenX screenY
相对于电脑屏幕的坐标
键盘事件
-
keyup 按键弹起的时候触发
-
keydown 按键按下
-
keypress 某个按键按下时触发 ,不识别功能按键 ctrl shift 等
按键被按下,执行顺序四 down --> press --> up
e.key
返回按下键的值
e.keyCode
返回按下键的ASCII值
常用事件 补充
contextmenu 上下文菜单,当用户右击元素时将显示上下文菜单
如何禁止有鼠标右键复制
document.addEventListener('contextmenu',function(e){
e.preventDefault();
});
鼠标选择文字 selectstart
阻止用户鼠标选中文字
document.addEventListener('selectstart', function (e) {
e.preventDefault();
});