Vue 2.x 移動端長按事件實現方式

vue 移動端長按事件實現的幾種方法的總結

你們好啊,我是大家的攻城獅,我是 Ken,人賤賤愛的前端攻城獅,我要告訴你個嚴重的問題,這幾天心情低落,代碼擼不動啊,結果今天一到公司,打開禪道,你們可能不知道什麼是 禪道 就是專門給程序猿提各類 bug 的地方,一早來了三個 bug,頓時一萬個草泥馬從腦門飄過:前端

圖片

最後我仍是慫了,咱們來看看究竟是什麼 bug?一看挖槽,原來是兼容性問題,你知道嗎?作前端最懼怕的是什麼呢?就是尼瑪的兼容,尤爲是有一個頑固的瀏覽器,IE,這個千刀萬剮的傢伙,禍害了多少代的程序猿,哈哈,幸虧的是咱們只須要兼容移動端,pc 端的網站須要兼容 ipad 端。vue

接下來看看是什麼問題?原來是在 pc 端右鍵菜單不能出現了,我一看原來是沒有兼容移動端的事件,由於在 pc 端咱們只須要使用 @contextmenu 這個事件就能夠實現右鍵菜單的出現了,node

固然在此以前咱們須要實現一個菜單組件,咱們這個菜單可能須要兼容二級菜單,因此須要實現二級菜單:express

<template>
  <!-- 右鍵菜單 -->
  <ul class="menu" v-show="show">
    <li
      :key="index"
      @click="clickOuterEvent(clickMenu.fnName, clickMenus.text)"
      class="menu-item icon-right-arrow"
      v-for="(clickMenu,index) in clickMenus"
    >

      <i class="menu-item-bg"></i>
      {{clickMenu.text}}
      <span class="right-arrow" v-show="clickMenu.secondaryMenu"></span>
      <ul class="secondary-menu">
        <li
          :key="index"
          @click.stop="clickEvent(item.fnName, item.text)"
          class="menu-item"
          v-for="(item,index) in clickMenu.secondaryMenu"
        >

          <i class="menu-item-bg"></i>
          {{item.text}}
        </li>
      </ul>
    </li>
  </ul>
</template>

這其中有一個邏輯當右鍵時,右鍵菜單纔會出現,因此須要一個控制右鍵菜單 menuShow ,固然咱們也須要知道菜單名稱是什麼,就須要一個數組來控制 clickMenus :數組

<script>
export default {
  name'fyMenu',
  props: {
    menuShow: {
      typeBoolean,
      defaultfalse,
    },
    clickMenus: {
      typeArray,
      default() => {
        return []
      },
    },
    // 鼠標右鍵菜單
    contextmenu: {
      typeObject,
      defaultfunction _default({
        return { height0width-10 }
      },
    },
  },
  data() {
    return {
      showthis.menuShow,
    }
  },
  methods: {
    clickOuterEvent(name, text) {
      this.$emit('update:menu-show'false)
      this.$emit('clickOuterEvent', name, text)
    },
    clickEvent(name, text) {
      this.$emit('update:menu-show'false)
      this.$emit('clickEvent', name, text)
    },
    getShow() {
      this.show = false
    },
    documentListen() {
      document.addEventListener('click'this.getShow, false)
    }
  },
  watch: {
    menuShow(val) {
      this.show = val
    },
  },
  mounted() {
    this.documentListen()
  },
  beforeDestroy() {
    document.removeEventListener('click'this.getShow, false)
  }
}
</script>

在外面的組件咱們應該這樣使用:瀏覽器

<fy-menu
 :clickMenus="clickMenus"
 :menu-show="showMenu"
 @clickOuterEvent="clickEvent"
 ref="menu"
></fy-menu>

export default {
    data() {
        return {
            clickMenus: [
            {
              fnName: 'modifyGroup',
              text: '編輯',
            },
            {
              fnName: 'combineGroup',
              text: this.ufd.text['text.plan.combine.group'],
            },
            {
              fnName: 'delete',
              text: this.ufd.text['text.del'],
            },
          ],
          showMenu: false, /
/ 展現菜單標誌
        }
    },
    methods: {
        clickEvent(name){}
    }
}

接下來咱們須要瞭解下移動端事件,由於移動端不像 pc 端同樣有鼠標事件,移動端只有觸摸事件:ide

今天咱們處理 bug 的使用最簡單的一種方式,就是使用 @touchstart@touchend函數

// 實現移動端長按出現右鍵菜單
start(e, group, nodeIndex, dayIndex, dayPriceSort, groupIndex) {
    clearTimeout(this.loop) //再次清空定時器,防止重複註冊定時器
    let that = this
    this.loop = setTimeout(() => {
        that.ipadMenucontext(e, group, nodeIndex, dayIndex, dayPriceSort, groupIndex)
    }, 1000)
},
end(e) {
    e.preventDefault()
    clearTimeout(this.loop) //清空定時器,防止重複註冊定時器
},

咱們能夠看到使用經過延遲函數裏執行咱們右鍵時須要處理的動做,在咱們手指開始觸摸時,須要先使用 clearTimeout 先清除上一次的定時器,再去執行咱們想要執行的動做,再觸摸結束以後,咱們須要清除定時器oop

圖片

因此這樣處理完成以後,咱們能夠在 ipad 端看到當咱們手指長按 iPad 屏幕的時候,右鍵菜單就會出現了。網站

圖片

以上就是移動端長按實現右鍵菜單。

接下來就是總結

總結

在vue中長按事件並無封裝,在使用的時候須要咱們本身取寫一個方法獲取長按事件。

方法一:使用@touchstart,@touchend

start () {
    clearTimeout(this.loop); //再次清空定時器,防止重複註冊定時器
    this.loop = setTimeout(() => {
        console.log("長按了");
    }, 1000);
},
 end () {
     clearTimeout(this.loop); //清空定時器,防止重複註冊定時器
 },

備註

備註:使用的時候注意若是是圖片,建議把圖片設置爲背景,直接使用圖片,在長按時會觸發瀏覽器對圖片的保存、分享等。

方法二:

指令

export default {

  install(Vue, options = {

    time2000,

  }) {

    Vue.directive('longpress', {

      bindfunction(el, binding, vNode{

        if (typeof binding.value !== 'function') {

          const compName = vNode.context.name

          let warn = `[longpress:] provided expression '${binding.expression}' is not afunction, but has to be `

          if (compName) { warn += `Found in component '${compName}' ` }

          console.warn(warn)

        }

        // 定義變量

        let pressTimer = null

        // 定義函數處理程序

        // 建立計時器( 1秒後執行函數 )

        let start = (e) => {

          if (e.type === 'click' && e.button !== 0) {

            return

          }

          if (pressTimer === null) {

            pressTimer = setTimeout(() => {

              // 執行函數

              handler()

            }, options.time)

          }

        }

        // 取消計時器

        let cancel = (e) => {

          // 檢查計時器是否有值

          if (pressTimer !== null) {

            clearTimeout(pressTimer)

            pressTimer = null

          }

        }

        // 運行函數

        const handler = (e) => {

          // 執行傳遞給指令的方法

          binding.value(e)

        }

        // 添加事件監聽器

        el.addEventListener('mousedown', start)

        el.addEventListener('touchstart', start)

        // 取消計時器

        el.addEventListener('click', cancel)

        el.addEventListener('mouseout', cancel)

        el.addEventListener('touchend', cancel)

        el.addEventListener('touchcancel', cancel)

      },

    })

  },

}

人生代碼 發起了一個讀者討論有時候問題歡迎你們加入討論啊,給我一些建議啊,否則我都聽不到粉絲的聲音

相關文章
相關標籤/搜索