vue3+TS 自定義指令:長按觸發繫結的函式

bbigger004發表於2022-12-29

vue3+TS 自定義指令:長按觸發繫結的函式

偶然間看到一個在vue2中寫的長按觸發事件的自定義指定,想著能不能把他copy到我的vue3專案中呢。

編寫自定義指令時遇到的幾個難點

1.自定義指令的型別

在ts中寫任何東西都要考慮到型別的問題,自定義指令的型別問題依然存在

2.在ts中使用setTimeout() 函式

setTimeout()函式的預設返回值是一個隨機的number ,這個number 代表了這個計時器的唯一id,但是並不能直接將其型別定義為number 否則會出現報錯。

3.自定義指令的傳參問題

我這裡的傳參方法只做參考,寫的很不規範。具體的好多傳參的方法請自行搜尋

程式碼

這個是我自己編寫的長按觸發繫結的函式
directives/longPress.ts

import { ObjectDirective } from 'vue'

const LongPress: ObjectDirective = {
  // 元件mounted時執行指令
  mounted(el, binding, vNode) {
    // 確保提供的表示式是函式
    if (typeof binding.value !== 'function') {
      // // 將警告傳遞給控制檯
      let warn = `[longpress:] provided expression '${binding.value}' is not afunction, but has to be `
      console.log(warn)
    } else {
      console.table({ el, binding, vNode })
      let timer: ReturnType<typeof setTimeout> | null = null  //定義空 定時器
      const start = (e: MouseEvent | TouchEvent) => {
        console.log(e)
        //下列事件不執行1.不是滑鼠左鍵2.單擊事件  (3.沒有傳入長按時間 ?? 有預設)
        if ((<MouseEvent>e).button !== 0 && e.type === 'click') {
          return
        }
        if (timer == null) {
          timer = setTimeout(() => {
            handler()
          }, Number(binding.arg) * 1000 ?? 0.5 * 10000) //預設長按0.5秒執行繫結的函式
        }
      }
      const cancel = () => {
        if (timer !== null) {
          clearTimeout(timer)
          console.log(timer);//定時器預設返回一個隨機的number 這個number的值是這個定時器的id
          timer = null
        }
      }
      const handler = () => {
        binding.value()
      }
      // 新增事件監聽器
      el.addEventListener('mousedown', start)
      el.addEventListener('touchstart', start)
      // 取消計時器
      el.addEventListener('click', cancel)
      el.addEventListener('mouseout', cancel)
      el.addEventListener('touchend', cancel)
      el.addEventListener('touchcancel', cancel)
    }
  },
}

export default LongPress

在main.ts中引入 作為全域性自定義指令

import { createApp } from 'vue'
import App from './App.vue'
import LongPress from './directives/longpress'

const app = createApp(App)
app.directive('longPress',LongPress)
app.mount('#app')

在元件中使用
這裡的v-longPress 便是自定義指令,其中此處的引數傳遞方法僅供參考

<template>
  <div>
    <button v-longPress = 'longFunc,1' >longPress</button>
  </div>
</template>

<script setup lang="ts">
const longFunc = () => {
  console.log('click long btn');
  alert('click long btn')
}
</script>

<style scoped>

</style>

相關文章