JavaScript的事件机制

1、事件流

事件流:是指页面接受事件的顺序,它包含了三个阶段,事件捕获阶段、目标阶段、事件冒泡阶段

<html>
    <body>
        <div>
            <button>单击按钮</button>
        </div>
    </body>
</html>

如上代码块,事件流顺序为:假如我们单击一下button,实际上先单击document,事件接着传递到HTML节点,再到body节点、div节点,最后到达button节点。到达button节点后,冒泡阶段就会按照相反的顺序从button节点返回document节点。
事件流程

2、DOM 0级事件

el.onclick = function(){};
实例代码:

<!DOCTYPE HTML>
<html>
<body>
<div>
    <button id="button">click</button>
</div>
<script>

var  button=document.getElementById("button");
button.onclick=function(){
    console.log('第一次注册click事件');
}
button.onclick=function(){
    console.log('第二次注册click事件');
}
button.onclick=function(){
    console.log('第三次注册click事件');
}
</script>
</body>
</html>
  • DOM 0事件不允许为同一个元素绑定多个同类型事件,当多次绑定时,只有最后一次绑定会生效,
  • DOM 0事件绑定方法默认是在事件行为冒泡阶段执行的。

DOM 0事件

3、DOM 2级事件

element.addEventListener(event, function, useCapture)

  • event : 指定事件名。注意不要使用“on”前缀,例如使用“click”而不是使用“onclick”;
  • function:指定要事件触发时执行的函数;
  • useCapture:布尔值,指定事件是否在捕获或冒泡阶段执行。默认是false,事件在冒泡阶段执行;
    DOM2级注册事件相比于DOM0级的优势就在于其可以多次注册,并且执行顺序与注册顺序一致。

4、事件的执行顺序

因为一些事件有一些默认行为,比如超链接单击跳转等等,那么事件的执行顺序是什么样子的呢?
一般事件执行顺序为:

事件捕获阶段
目标阶段
事件冒泡阶段
事件默认行为

正是因为事件的默认行为是最后执行的,我们才有机会阻止事件默认行为。

//阻止文本框获取焦点
var input = document.getElementById("input");
input.addEventListener('mousedown',function(e){
	e = event || window.event;
	if(e.preventDefault){
		e.preventDefault();
	}else{//IE浏览器组织默认事件行为
		e.returnValue = false;
	}
})

5、事件冒泡阶段案例


<!DOCTYPE HTML>
<html>
<body>
<style>
	*{color:white}
	#btn{width:200px;height:200px;background:red;}
	#btn1{width:120px;height:120px;background:green;}
	#btn2{width:60px;height:60px;background:blue;}
</style>
<div id='btn'>
爷爷
    <div id='btn1'>
		父亲
		<div id='btn2'>孩子</div>
	</div>
</div>
<!-- <input id='input' type="text"> -->

<script>

var btn=document.getElementById("btn");
var btn1=document.getElementById("btn1");
var btn2=document.getElementById("btn2");
btn.onclick=function(){
    console.log('单击了爷爷');
}
btn1.onclick=function(){
    console.log('单击了父亲');
}
btn2.onclick=function(){
    console.log('单击了孩子');
}
</script>
</body>
</html>

单击孩子
单击父亲
单击爷爷

6、常见用法

(1)阻止默认事件触发

event.preventDefault() 阻止默认事件触发

例如有时候我们只想用标签当作一个普通按钮,不想让它跳转。此时我们可以用如下方法:

//方法一
<a href="javascript:;">link</a>
//方法二
<a id="link" href="http://www.cnblogs.com">链接</a>
<script>
var link = document.getElementById('link');
link.onclick = function(e){
    e = e || window.event;
    return false;
}
</script>
//方法三
<a id="link" href="http://www.cnblogs.com">链接</a>
<script>
var link = document.getElementById('link');
link.onclick = function(e){
    e = e || window.event;
    e.preventDefault();
}
</script>

(2)阻止事件冒泡到父元素

event.stopPropagation() //阻止事件冒泡到父元素

inner.onclick = function(e){
	e.stopPropagation();
}

e.stopImmediatePropagation(); 既能阻止事件向父元素冒泡,也能阻止元素同事件类型的其它监听器被触发。而stopPropagation只能阻止向父元素冒泡。

<button id='button'>阻止事件</button>

<script>
var btn=document.getElementById("button");
btn.addEventListener('click',function(e){
	console.log('单击一次');
    e.stopImmediatePropagation();
})
btn.addEventListener('click',function(e){
	console.log('单击二次');
})
btn.addEventListener('click',function(e){
	console.log('单击三次');
})
</script>

双重阻止

(3)事件委托

由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)。

优点:

  • 减少内存消耗,提高性能
  • 动态绑定事件
    如何实现
<ul id="list">
  <li>item 1</li>
  <li>item 2</li>
  <li>item 3</li>
</ul>
<script>
// 给父层元素绑定事件
document.getElementById('list').addEventListener('click', function (e) {
  // 兼容性处理
  var event = e || window.event;
  var target = event.target || event.srcElement;
  // 判断是否匹配目标元素
  if (target.nodeName.toLocaleLowerCase === 'li') {
    //需要处理的事务
  }
});
</script>

(4)event.target & event.currentTarget

先看看例子:
currentTarget
event.target是事件的真正发出者,而event.currentTarget是当前监听者。
只有被单击的目标元素的event.target才会等于event.currentTarget。
参考资料:
Lazymr
前端浪人

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值