事件传播机制
事件:
JavaScript和HTML的交互是通过事件实现的
事件是某个行为或者触发,比如点击、鼠标移动:
- 当用户点击鼠标时
- 当网页已加载时
- 当图像已加载时
- 当鼠标移动到元素上时
- 当用户触发按键时
事件流
-
事件冒泡
事件开始时由最具体的元素接受,然后逐级向上传播到较为不具体的元素
-
事件捕获
不太具体的节点更早接受事件,而最具体的元素最后接受事件,和事件冒泡相反
-
DOM事件流
DOM2级事件规定事件流包括三个阶段,事件捕获阶段,处于目标阶段,时间冒泡阶段,首先发生的是事件捕获,为截取事件提供机会,然后是实际目标接受事件,最后是冒泡阶段
注:Opera、Firefox、Sarfari都支持DOM事件流,IE不支持事件流,只支持时间冒泡
阻止传播
stopPropagation()
方法
定义和用法
不再派发事件。
终止事件在传播过程的捕获、目标处理或起泡阶段进一步传播。调用该方法后,该节点上处理该事件的处理程序将被调用,事件不再被分派到其他节点。
说明
该方法将停止事件的传播,阻止它被分派到其他 Document 节点。在事件传播的任何阶段都可以调用它。注意,虽然该方法不能阻止同一个 Document 节点上的其他事件句柄被调用,但是它可以阻止把事件分派到其他节点。
语法
event.stopPropagation()
注意: IE浏览器的后面几个版本都 支持了W3C标准,之前有个别版本不支持
event在IE不支持的版本中,是无法接收到事件的,并且没有stopProgapation
方法
火狐、google及最新的IE版本的结束事件都支持stopPropagation()
方法来结束默认行为
老版本的IE如想结束默认行为,须要使用window.event.cancelBubble = true;
方法
取消默认事件
preventDefault() 方法
什么是事件默认行为?
- a链接默认跳转
- type =submit默认提交表单
- 其他浏览器默认行为...
定义和用法
preventDefault()
方法阻止元素发生默认的行为(例如,当点击提交按钮时阻止对表单的提交)。
示例: 阻止a链接进行跳转,并输出a链接
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<a href="http://baidu.com">百度</a>
<script type="text/javascript">
document.querySelector('a').onclick = function(e) {
e.preventDefault()
console.log(this.href)
}
</script>
</html>
事件代理
委托事件也叫做事件代理意思是一样的,就好像精灵图也叫 雪碧图!!!只是不同叫法.
试想一下:假设公司里每次收快递的时候员工都跑到公司门口去收自己的快递,如果同时多个人也同样去收自己快递这样公司就秩序混轮了!如果委托给前台妹子去收快递然后由妹子去派发快递这个过程就叫委托事件!(备注:冒泡思想也有点相仿只不过是由父节点往子节点传递信息)
<style>
div {
width: 500px;height: 300px;border: 2px solid tomato;border-radius: 5px;margin: 100px auto;padding: 20px;
}
#oul{
margin: 0;padding: 0;width: calc(100% - 20px);height: calc(100% - 20px);border: 2px solid gray;border-radius: 5px;padding: 10px;
}
#oul li {
width: 100%;height: 30px;background: #999;list-style: none;border-radius: 5px;color: #fff;text-align: center;line-height: 30px;margin-bottom: 5px;
}
</style>
<div>
<ul id="oul" >
<li>item_1</li>
<li>item_2</li>
<li>item_3</li>
<li>item_4</li>
<li>item_5</li>
<li>item_6</li>
<li>item_7</li>
<li>item_8</li>
</ul>
</div>
<script>
var oul = document.getElementById('oul');//使用事件委托方式
oul.onclick = function (ev) {
var ev = ev || window.event;
var target = ev.target || evsrcElement;
if(target.nodeName.toLowerCase() == 'li'){//nodeName的意思获得DOM元素的节点名称 //toLowerCase()的方法用以是,把获取到的节点名称转换为小写
console.log(target.innerHTML)
}
}
</script>
优点:
1.可以大量节省内存占用,减少事件注册。比如ul上代理所有li的click事件就很不错。
2.可以实现当新增子对象时,无需再对其进行事件绑定,对于动态内容部分尤为合适
缺点:
事件代理的常用应用应该仅限于上述需求,如果把所有事件都用事件代理,可能会出现事件误判。即本不该被触发的事件被绑定上了事件。