DOM事件、事件流

制作“点击别处关闭浮层”效果

  • debugger
  • event.stopPropagation()这个方法用于阻止事件的传播
  • 用css制作一个小三角
#triangle{
    border:10px solid transparent;
    border-right:5px solid red;
}
  • 在某元素上添加了 preventDefault() 会导致它本身和它的子元素里的checkbox()无法被点击(因为默认动作都被阻止了)

    此时无法点击checkbox

  • 如何节省监听器内存?
    在实际网页中我们只需要在浮层弹出时设定一个一次性事件监听器

$('button').on('click',function(x){
    $(popover).show()
    $(document).one('click',function(x){
        $(popover).hide()
    })
})

这样在浮层没有被弹出时,不对document进行监听,就很好的减少了内存的使用

  • 如何解决下图一个小bug?(两种方法)
    如果代码照下面写,会导致点击按钮后浮层不弹出的问题
$('button').on('click', function (x) {
    $(popover).show()
    console.log('展示浮层')
    $(document).one('click', function (x) {
        $(popover).hide()
        console.log('隐藏浮层')
    })
}) 
控制台结果

可以看到同时执行了两个函数,这是因为在‘click’事件的target阶段就已经将document的监听器设定好了,等到‘click’事件冒泡到document时一次性监听器中的函数就会被执行
方法1:给button的父级元素添加 event.stopPropagation()方法

//此时button的父级元素是wrapper
wrapper.addEventListener('click',function(x){
    x.stopPropagation()
})

方法2:用setTimeout()

$('button').on('click', function (x) {
    $(popover).show()
    console.log('展示浮层')
    setTimeout(function () {
        $(document).one('click', function (x) {
            $(popover).hide()
            console.log('隐藏浮层')
        })
    }, 0)
})
  • setTimeout(()=>{},0) 是如何实现异步操作的
  • 最终代码
    $('#btn').on('click',function () {
      $('#popover').toggleClass('show')
      .one('click',()=>{
        setTimeout(function () {
        $(document).on('click',function () {
          $('#popover').removeClass('show');
        })
      },0)
      })
    })
    $('#wrap').on('click',function (e) {
      e.stopPropagation();
    })

DOM事件的进一步了解

http://js.jirengu.com/jamirapaqi/1/edit

无缝轮播

  • 无缝轮播一个bug:从其他页面切换回无缝轮播页面的时候,会出现轮播乱了的情况(自己做做看),原因在于浏览器在页面切出去后不会执行setInterval()的内容,在等用户切回页面之后,再同时执行setInterval()的内容,这导致了轮播可能出现混乱
  • 解决方法1:通过监听visibilitychange事件,在用户没有看该页面时把setInterval()停掉,代码如下:
 document.addEventListener('visibilitychange', function (x) {
    if (document.hidden) { ///如果当前页面没有被浏览就不要再执行轮播
        window.clearInterval(timer)
    } else {///如果切换回轮播页面,重新启动轮播效果
        timer = setInterval(() => {
            slide(n)
            n++
        }, 1500)
    }
})

document.hidden返回布尔值,用于查看当前页面是否被浏览
这可以防止轮播混乱

  • 要实现又能点击切换图片又能无缝轮播
    用到element属性:outerHTML
    用到以下jQueryAPI
    clone()
    append()末尾插入元素,可以接受DOM元素、jQ对象、字符串
    prepend()最前面插入元素,可以接受DOM元素、jQ对象、字符串
  • 在一句代码中出现hide()show(),浏览器可能会同时处理,没办法达到想要的效果。此时在中间加入offset(),会使浏览器不同时进行offset()show(),达到想要的效果
    .offset()返回一个对象,该对象包含jQ对象相对于document的位置
$(btn).eq(0).on('click',()=>{
  if(current === 2){
    $slide.css({'transform':'translateX(-1200px)'})
    .one('transitionend',()=>{           
           $slide.hide().offset()
           $slide.css({'transform':'translateX(-400px)'})//.offset()返回的不是jQ对象所以不能直接链式操作            
      })    
  }
})

猜想用setTimeout(fn,0)也能实现相同效果,但发现在切换的动画过程中会有闪烁

$btn.eq(0).on('click',()=>{
    if(current === 2){
        $slide.css({'transform':'translateX(-1200px)'})  
        .one('transitionend',()=>{
            $slide.hide()
            setTimeout(() => {
                $slide.css({'transform':'translateX(-300px)'}).show()
            }, 0);
            
        })

事件流

事件流描述的是事件在页面中传播的顺序,它包括三个阶段:捕获阶段、目标阶段、冒泡阶段。
在DOM2级事件中,用addEventListener()来处理事件。该函数接受三个参数,由第三个参数决定事件被触发后回调函数在哪个阶段被执行,该参数默认为false,即冒泡阶段被执行。
需要注意的是,触发事件时嵌套最深,最底层的那个元素,它没有冒泡和捕获阶段,仅有目标阶段。而在目标阶段,回调函数的执行顺序只由代码的顺序决定。

你可能感兴趣的:(DOM事件、事件流)