站点工具

用户工具


手写fastclick

fastclick 原理

在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后真正触发的click事件阻止掉

自制简易fastclick

const FastClick = (function(){
 
  function attach(root) {
    let targetElement = null
    root.addEventListener('touchstart', function () {
      targetElement = event.target
    })
    root.addEventListener('touchend', function (event) {
      event.preventDefault()
      let touch = event.changedTouches[0]
      let clickEvent = document.createEvent('MouseEvents')
      clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null)
      clickEvent.forwardedTouchEvent = true 
      targetElement.dispatchEvent(clickEvent)
    })        
  }
 
  return { attach }
})()
 
FastClick.attach(document.body)

测试fastclick

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>fastclick简单实现-饥人谷</title>
  <meta name="viewport" content="width=device-width">
</head>
<body>
  <p>用手指放大页面,再点链接测试</p>
  <p id="log"></p>
 
  <div class="box box1">
    <h3>未使用fastclick有岩石</h3>
    <a id="link1" href="#1">链接1</a> 
    <a id="link2" href="#2">链接2</a>
  </div>
 
  <div class="box box2">
    <h3>使用fastclick无延时</h3>
    <a id="link3" href="#3">链接3</a> 
    <a id="link4" href="#4">链接4</a>
  </div>
 
  <script>
 
    const $ = selector => document.querySelector(selector)
    const $$ = selector => document.querySelectorAll(selector)
    const log = str => $('#log').innerText = str 
 
    const FastClick = (function(){
      function attach(root) {
        let targetElement = null
        root.addEventListener('touchstart', function () {
          targetElement = event.target
        })
        root.addEventListener('touchend', function (event) {
          event.preventDefault()
          let touch = event.changedTouches[0]
          let clickEvent = document.createEvent('MouseEvents')
          clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null)
          clickEvent.forwardedTouchEvent = true 
          targetElement.dispatchEvent(clickEvent)
        })        
      }
      return { attach }
    })()
 
    FastClick.attach($('.box2'))
 
 
    let start
 
    $$('a').forEach($link => {
      $link.ontouchend = () => {
        start = Date.now()
      }
    })
 
 
    window.onhashchange = () => {
      log(`click link ${location.hash}: ${Date.now() - start }ms`)
    }
  </Script>
</body>
</html>

测试时,先用双指放大页面,此时才会出现点击延时。 分别对比使用fastclick处理过的区域和未处理过的区域。 复制链接到手机浏览器 http://js.jirengu.com/goxaq image.png

若愚 · 2021/09/16 15:37 · 移动端_fastclick.txt