DOM 事件模型2:阻止冒泡,popover,轮播BUG解决

  • Post author:
  • Post category:其他


DOM 事件模型2:阻止冒泡,popover,轮播BUG解决

1从popover(点击别处关闭浮层)理解冒泡与捕获



PK8Pv4.png

当几个DIV嵌套,触发事件时,是先进行捕获阶段的触发,再进行冒泡阶段的触发的.

例如一个popover的例子

想要的效果是点击别处关闭浮层

如图:



PMWijg.png

demo链接:


http://js.jirengu.com/soyet/4/



PMWkuQ.png



点击时触发了console.log函数,说明触发了document的点击事件,可是为什么没有出现浮层呢?

因为两次addEventListener是没有加参数的,所以以冒泡阶段执行两个事件,当点击点我按钮,结果是依次触发点我按钮的click事件和document的click事件.所以没有想要效果



PMW3DJ.png

加上

debugger

后发现两个函数确实都执行了,



PMWJER.png

2阻止冒泡 event.stopPropagation()

Propagation翻译:传播

stopPropagation,停止传播,不要再告诉父母了,不要再往上执行冒泡事件了

示例代码:


http://js.jirengu.com/soyet/8…




PMWDDH.png





PMfpZ9.png

2.1解决BUG

但是出现一个bug.当我点击点我按钮,浮层不会消失,但是当我点击浮层,浮层还是会消失,我想让浮层被点击时也不消失,只是点击其他地方消失,该如何做呢?

示例代码:


http://js.jirengu.com/faquz/2…



PMfkRK.png



将阻止冒泡事件加在wrapper上,这样当冒泡执行到wrapper时,就不会再继续往上传播,即到wrapper就停止了



PMfoQO.png

2.2jQuery的一个BUG



PMhc1f.png


$(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无法点击了,复选框无法选中,所以不要这样写



PMhXB4.png

正确写法如下



PM4S41.png




http://js.jirengu.com/pebok/1…

2.3内存问题,如何优化

假如页面中有很多popover,那么每个document都要添加监听点击事件.这样浪费内存

解决方法:不一直监听document,只有当popover出来的时候才监听,且只监听一次,当点击完document,就清除了监听事件.这样节省内存



PM4UCq.png



示例代码:

http://js.jirengu.com/mivaf/2…

2.3.1引出另一个问题,



PM4rb4.png



实例代码:


http://js.jirengu.com/waral/2…


去掉阻止冒泡事件,按理来说,点击button,知识添加了document的点击事件,而为什么有触发了document的点击事件呢?

因为代码是按照同步执行的规则来的,同步事件

,即一步一步的执行,这一步没有完成,不会进行下一步.当点击了btn,会把点击事件添加到document,然后冒泡才继续往上执行.

图解:



PM44KO.png

解决方法:

让这个添加监听事件函数慢一点执行,等冒泡阶段走完再执行


PM4ORP.png

代码:


http://js.jirengu.com/madin/1…

接下来再证明这一点:



PM5iin.png



示例代码:


http://js.jirengu.com/kehut/2…

3冒泡可视化

示例代码


http://js.jirengu.com/wotoz/5…


实际上是一次解析完毕



PMHd2R.png

4轮播BUG解决

4.1 切换标签页setInterval不工作BUG

浏览器有一个BUG,当页面标签切换时,setInterval回不工作或间歇性工作.例如

每秒打印两次日期,当切换别的标签页,再切回来时发现,setInterval只打印了一次,说明setInterval间歇工作



PMbXkD.png

解决方法:

浏览器标签页被隐藏或显示的时候会触发

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/



PMqt39.png

修改轮播代码:

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);
    }
});


预览地址



完整代码地址