从popover(点击别处关闭浮层)理解冒泡与捕获
image.png当几个DIV嵌套,触发事件时,是先进行捕获阶段的触发,再进行冒泡阶段的触发的.
例如一个popover的例子
想要的效果是点击别处关闭浮层
如图:
点击时触发了console.log函数,说明触发了document的点击事件,可是为什么没有出现浮层呢?
因为两次addEventListener是没有加参数的,所以以冒泡阶段执行两个事件,当点击点我
按钮,结果是依次触发点我
按钮的click事件和document
的click事件.所以没有想要效果
加上debugger后发现两个函数确实都执行了,
image.png阻止冒泡 event.stopPropagation()
Propagation翻译:传播
stopPropagation,停止传播,不要再告诉父母了,不要再往上执行冒泡事件了
3.1解决一个BUG
但是出现一个bug.当我点击点我按钮,浮层不会消失,但是当我点击浮层,浮层还是会消失,我想让浮层被点击时也不消失,只是点击其他地方消失,该如何做呢?
image.png将阻止冒泡事件加在wrapper上,这样当冒泡执行到wrapper时,就不会再继续往上传播,即到wrapper就停止了
3.2 jQuery的一个BUG
image.png$(wrapper).on("click",false);
jQuery的添加 监听事件中,如果在后面加上一个参数false,那么相当于下面的代码
$(wrapper).on("click",function(el){
el.preventDefault();
el.stopPropagation();
});
preventDefault 是另外一个相关的方法,它可以阻止事件触发后默认动作的发生。
即既阻止默认事件,又阻止冒泡事件.
但是这样会出现一个BUG.
因为给wrapper加了 el.preventDefault();
组织了默认事件,所以input无法点击了,复选框无法选中,所以不要这样写
如何修改呢???
可以点击input内存问题,如何优化
假如页面中有很多popover,那么每个document都要添加监听点击事件.这样浪费内存
解决方法:不一直监听document,只有当popover出来的时候才监听,且只监听一次,当点击完document,就清除了监听事件.这样节省内存
上面的做法就是在点击按钮的时候,才添加监听事件,并且只监听一次,节省内存
引出bug
image.png当点击点我这个按钮的时候,不仅触发了按钮的点击事件,而且还触发了document的事件
去掉阻止冒泡事件,按理来说,点击button,只是添加了document的点击事件,而为什么又触发了document的点击事件呢?
因为代码是按照同步执行的规则来的
同步事件
即一步一步的执行,这一步没有完成,不会进行下一步.当点击了btn,会把点击事件添加到document,然后冒泡才继续往上执行.
图解:
解决方法:
让这个添加监听事件函数慢一点执行,等冒泡阶段走完再执行
在这里面的setTimeout时间设置为0,并不是立即执行,而是尽快执行。即等一会就执行,等冒泡阶段结束了在执行,在添加document
的点击事件
上面的执行顺序是:先执行冒泡事件,在执行setTimeout中的内容
冒泡可视化
image.png实际上是一次解析完毕
网友评论