视口控制

1
2
3
4
<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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
  • 事件的作用在于实现移动端的界面交互

触摸被打断

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

点击穿透

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

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

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

解决方案

  1. 阻止默认行为

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

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

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

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

页面跳转的选择

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

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