再次总结移动端事【件穿穿透】问题

整体代码

<!DOCTYPE html>
<html>

<head>
  <meta charset=utf-8>
  <meta name=viewport content="width=device-width,initial-scale=1">
  <title>vui</title>
</head>
<style>
    #app {
        width: 100px;
        height: 100px;
        position: absolute;
        left: 0;
        top: 0;
        z-index: 2;
        background-color: red;
    }

    .dow {
        width: 300px;
        height: 300px;
        position: absolute;
        left: 0;
        top: 0;
        background-color: blue;
    }
</style>
<body>
  <div class="dow">
        <div id=app>

        </div>
  </div>
  <script >
  let app = document.querySelector('#app')
  let dow = document.querySelector('.dow')
//   app.ontouchstart = function () {
//     console.log('app click')
//   }
  app.addEventListener('touchstart', function (e) {
    app.style.display = 'none'
    console.log('app click')
    e.preventDefault();
    e.stopPropagation();
  })

  dow.addEventListener('click', function () {
    console.log('dow click')
  })

  // touchstart 事件只能通过dom2方式 (也就是addEventListener传播)以下这种方式无响应的
//   dow.ontouchstart = function () {
//     console.log('dow click')
//   }
  </script>

</body>

</html>

事件穿透 不是 事件冒泡

1事件冒泡

事件冒泡存在的前提是层级嵌套

如: 这种情况下 两个元素都绑定click事件 或者touchstart事件,点击 app时 事件会冒泡到dow上

  <div class="dow">
        <div id=app>

        </div>
  </div>

如: 这种情况下 两个元素都绑定click事件 或者touchstart事件,点击 app时 事件不会冒泡

  <div id=app>

  </div>
  <div class="dow">

  </div>

总结: 由于body是所有dom的父层级,所以 任何事件都会冒泡到body上

2事件穿透

存在前提:
  • 上层绑定 touchstart事件
  • 下层绑定click事件
  • 上层点击时候 隐藏自身
  • 与两个元素是嵌套 还是 上下层 无关

产生原因: touchstart 先与click执行

解决方案:

  app.addEventListener('touchstart', function (e) {
    app.style.display = 'none'
    console.log('app click')
	//重点
    e.preventDefault(); //组织事件默认事件,在事件touchstart时候就组织了继续往下产生click\touchend事件
    e.stopPropagation();//非必须 此方法主要组织冒泡,由于前面结论可知,仅当dom存在嵌套下才会产生冒泡才需要此方法
  })

"e.preventDefault(); //组织事件默认事件,在事件touchstart时候就组织了继续往下产生click\touchend事件" 的解释

  <div class="dow">
        <div id=app>

            </div>
  </div>

 app.addEventListener('touchstart', function (e) {
    app.style.display = 'none'
    console.log('app touchstart')
    e.preventDefault();
    e.stopPropagation();
  })
  app.addEventListener('touchend', function (e) {
        console.log('app end')
  })
  app.addEventListener('click', function (e) {
        console.log('app click')
  })
  dow.addEventListener('touchstart', function () {
    console.log('dow touchstart')
  })
  dow.addEventListener('click', function () {
    console.log('dow click')
  })

  dow.addEventListener('touchend', function (e) {
        console.log('dow touchend')
  })

运行点击结果

  • app touchstart
  • app end
  • dow touchend

翻译翻译

-对页面点击一次 会先后产生'touchstart' ----'touchend' ---- 'click'事件

我们对 app 绑定了 'touchstart' ----'touchend' ---- 'click' 并对 touchstart 绑定两个阻止方法
当我们点击app时候

产生 touchstart事件 ,由于对事件组织默认事件,所以接下来不会再产生click事件,也不会冒泡
产生 touchend事件 ,
冒泡 touchend事件 到dow上

补充两篇相关文章

最后的结论

移动端不建议用touch事件,弊端如代码只能在移动端使用,pc端无法使用,且ie内核可能无法兼容
用click事件 目前都用fastclick解决,其本质是在touchend事件中 触发click事件,并阻止默认的click事件,从而避免了300s延迟 和 事件 穿透

posted @ 2018-01-15 18:47  _白马非马  阅读(221)  评论(0编辑  收藏  举报