分享人:宋恒
目录
1.背景介绍
2.知识剖析
3.常见问题
4.解决方案
5.编码实战
6.扩展思考
7.参考文献
8.更多讨论
事件是监听在某个DOM元素上的,但是js的DOM事件有捕获和冒泡的机制,所以事件处理不是我们想的那样简单。 由于存在捕获和冒泡,所以事件的触发元素(目标源)不一定是当前的监听元素。于是就有一些问题,
DOM(文档对象模型)结构是一个树型结构,当一个HTML元素产生一个事件时,该事件会在元素结点与根节点之间按特定的顺序传播, 路径所经过的节点都会收到该事件,这个传播过程可称为DOM事件流。 简单理解为事件在页面的DOM节点之间传播的顺序,分为三个过程:事件捕获阶段 --> 事件目标阶段 --> 事件冒泡阶段
事件捕获:就是页面最外层的节点先接收事件,然后向内层元素逐级传播,比如从window ->document->html->body->div
事件冒泡:和捕获恰恰相反,让最内层先接受事件,然后向外层传播
事件目标阶段: target,不管是在传播阶段还是冒泡阶段,都必然经历目标阶段,就是对dom节点的事件进行处理
浏览器的一些默认的行为。例如:点击超链接跳转,点击右键会弹出菜单,滑动滚轮控制滚动条
需要先了解一些关键点:1.event事件对象 2.目标源:target 3.当前目标源:currentTarget 4.元素element
event对象代表事件的状态,比如事件在其发生的元素,键盘按键的状态,鼠标位置等。event对象只会在事件发生过程中存在。在触发的事件函数里, 我们会接收一个event对象,通过该对象去了解一些参数,比如要知道事件发生在谁身上,通过event的属性target来获取,方法是event.target。
target在事件流的目标阶段;currentTarget在事件流的捕获,目标及冒泡阶段。只有当事件流处在目标阶段的时候,两个的指向才是一样的, 而当处于捕获和冒泡阶段的时候,target指向被单击的对象而currentTarget指向当前事件活动的对象(一般为父级)。看一下demo
element对象表示html元素,可以拥有的类型为元素节点,文本节点,属性节点等
事件冒泡
在一个对象上触发某类事件(比如点击事件),如果此对象定义了此事件的处理程序, 那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播, 从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即document对象(有些浏览器是window)。(demo)
简单的说,就是我鼠标点击一个元素上,这个事件会在这个元素所有祖先元素中触发,一直冒泡到dom最上层想象一下现在我们有一个10列、100行的HTML表格,你希望在用户点击表格中的某一单元格的时候做点什么。 比如说我有一次就需要让表格中的每一个单元格在被点击的时候变成可编辑状态。如果把事件处理器加到这1000个单元格会产生一个很大的性能问题, 并且有可能导致内存泄露甚至是浏览器的崩溃。相反地,使用事件代理的话, 你只需要把一个事件处理器添加到table元素上就可以了,这个函数可以把点击事件给截下来,并且判断出是哪个单元格被点击了。
1.stopPropagation(),见demo
2.return false
javascript的return false只会阻止默认行为,而是用jQuery的话则既阻止默认行为又防止对象冒泡。见demo
可以使用preventDefault()方法,直接使用event对象调用即可
1.阻止冒泡的这两种方法的区别?
这两种方法是有区别的。return false不仅阻止了事件冒泡,还阻止了事件本身。 stopPropagation()方法只会阻止事件冒泡,不会阻止事件本身。
是否所有事件都会触发冒泡
focus、blur和scroll事件不会冒泡。文档元素上的load事件会冒泡,但它会在document对象上停止冒泡而不会传播到window对象
1.写在那一层里就阻止其冒泡行为。2.使用事件代理,$.on(),这其实是将事件监听(代理)在父元素上面,内部也是利用了冒泡的机制,并判断目标源,实现事件代理的。
感谢大家观看
宋恒