DOM 事件模型2:阻止冒泡,popover,轮播BUG解决
DOM 事件模型2:阻止冒泡,popover,轮播BUG解决
1从popover(点击别处关闭浮层)理解冒泡与捕获
当几个DIV嵌套,触发事件时,是先进行捕获阶段的触发,再进行冒泡阶段的触发的.
例如一个popover的例子
想要的效果是点击别处关闭浮层
如图:
demo链接:
http://js.jirengu.com/soyet/4/
点击时触发了console.log函数,说明触发了document的点击事件,可是为什么没有出现浮层呢?
因为两次addEventListener是没有加参数的,所以以冒泡阶段执行两个事件,当点击点我按钮,结果是依次触发点我按钮的click事件和document的click事件.所以没有想要效果
2阻止冒泡 event.stopPropagation()
Propagation翻译:传播
stopPropagation,停止传播,不要再告诉父母了,不要再往上执行冒泡事件了
示例代码:
http://js.jirengu.com/soyet/8...
2.1解决BUG
但是出现一个bug.当我点击点我按钮,浮层不会消失,但是当我点击浮层,浮层还是会消失,我想让浮层被点击时也不消失,只是点击其他地方消失,该如何做呢?
示例代码:
http://js.jirengu.com/faquz/2...
将阻止冒泡事件加在wrapper上,这样当冒泡执行到wrapper时,就不会再继续往上传播,即到wrapper就停止了
2.2jQuery的一个BUG
$(wrapper).on("click",false);
jQuery的添加 监听事件中,如果在后面加上一个参数false
,那么相当于下面的代码
$(wrapper).on("click",function(e){ e.preventDefault(); e.stopPropagation(); });
示例代码如下:
http://js.jirengu.com/salar/1...
preventDefault 是另外一个相关的方法,它可以阻止事件触发后默认动作的发生。
即既阻止默认事件,又阻止冒泡事件.
但是这样会出现一个BUG.
因为给wrapper加了 e.preventDefault();
组织了默认事件,所以input无法点击了,复选框无法选中,所以不要这样写
正确写法如下
http://js.jirengu.com/pebok/1...
2.3内存问题,如何优化
假如页面中有很多popover,那么每个document都要添加监听点击事件.这样浪费内存
解决方法:不一直监听document,只有当popover出来的时候才监听,且只监听一次,当点击完document,就清除了监听事件.这样节省内存
示例代码:http://js.jirengu.com/mivaf/2...
2.3.1引出另一个问题,
实例代码:
http://js.jirengu.com/waral/2...
去掉阻止冒泡事件,按理来说,点击button,知识添加了document的点击事件,而为什么有触发了document的点击事件呢?
因为代码是按照同步执行的规则来的,同步事件
,即一步一步的执行,这一步没有完成,不会进行下一步.当点击了btn,会把点击事件添加到document,然后冒泡才继续往上执行.
图解:
解决方法:
让这个添加监听事件函数慢一点执行,等冒泡阶段走完再执行
代码:
http://js.jirengu.com/madin/1...
接下来再证明这一点:
示例代码:
http://js.jirengu.com/kehut/2...
3冒泡可视化
示例代码
http://js.jirengu.com/wotoz/5...
实际上是一次解析完毕
4轮播BUG解决
4.1 切换标签页setInterval不工作BUG
浏览器有一个BUG,当页面标签切换时,setInterval回不工作或间歇性工作.例如
每秒打印两次日期,当切换别的标签页,再切回来时发现,setInterval只打印了一次,说明setInterval间歇工作
解决方法:
浏览器标签页被隐藏或显示的时候会触发visibilitychange
事件.
visibilitychange--MDN
document.addEventListener("visibilitychange", function() { console.log( document.visibilityState ); });
当页面标签切换出去,document.visibilityState
值为hidden
,再切换回来值为visible
用法2:
document.addEventListener("visibilitychange", function() { console.log( document.hidden ); });
当页面标签切换出去,document.hidden
值为true
,再切换回来值为false
示例代码:
http://js.jirengu.com/gejax/1/
修改轮播代码:
var timer = setInterval(()=>{ makeImgLeft(getImgN(n)) .one('transitionend',(e)=>{ makeImgRight($(e.currentTarget));//当前元素 }); makeImgMid(getImgN(n+1)); n+=1; },1000); document.addEventListener("visibilitychange", function() { if(document.hidden){ clearInterval(timer); }else{ timer = setInterval(()=>{ makeImgLeft(getImgN(n)) .one('transitionend',(e)=>{ makeImgRight($(e.currentTarget));//当前元素 }); makeImgMid(getImgN(n+1)); n+=1; },1000); } });