视口控制

<meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, user-scaleable=no, maximum-scale=1.0, minimum-scale=1.0"
      />

事件

845171ee-5e7b-46a5-8226-4725ef5cae5f

var box = document.querySelector('#box')
// 元素上触摸开始时触发
box.addEventListener('touchstart', function () {
  box.style.backgroundColor = 'red'
})
// 元素上触摸移动时触发
box.addEventListener('touchmove', function () {
  box.style.backgroundColor = 'yellow'
  console.log('touchmove触发了!')
})
// 手指从元素上离开时触发
box.addEventListener('touchend', function () {
  box.style.backgroundColor = 'blue'
})
  • touchmove 事件触发后,即使手指离开了元素,touchmove 事件也会持续触发
  • 触发 touchmove 与 touchend 事件,一定要先触发 touchstart
  • 事件的作用在于实现移动端的界面交互

触摸被打断

// 事件被打断
box.addEventListener('touchcancel', function () {
  box.style.backgroundColor = 'black'
})

点击穿透

touch 事件结束后会默认触发元素的 click 事件,如没有设置完美视口,则事件触发的时间间隔为 350ms 左右,如设置完美视口则时间间隔为 50ms 左右。

如果 touch 事件隐藏了元素,则 click 动作将作用到新的元素上,触发新元素的 click 事件或页面跳转,此现象称为点击穿透

9c465c2c-56c9-47c8-b1db-1a074721698a

解决方案

  1. 阻止默认行为

  2. 阻止顶级元素事件的默认行为,可以增加一个包裹元素绑定,也可以给 document 和 window 绑定,不过需要关闭被动模式

    document.addEventListener('touchstart', function(e){
    	e.preventDefault();
    }, {
    	passive: false
    });
  3. 使用非链接的元素代替 a 标签,并绑定 touchstart 事件

    <div class="item">
    	<div data-href="http://xiaokang.me"><img src="holder.js/60x60?bg=#a76"></div>
    </div>
  4. 延时隐藏遮盖元素

    setTimeout(function(){
    	el.style.display = 'none';
    }, 400)

页面跳转的选择

移动端页面跳转可以使用 a 链接,也可以使用 touchstart 事件来触发 JS 代码完成跳转

  • 效率上,touchstart 速度更快
  • SEO 优化上, a 链接效果更好