移動端的touch事件和click事件遇到的坑

我的博客查看文章點這裏html

項目需求:

(移動端項目中)長按聊天消息,出現一個彈出層,進行消息撤回操做,點擊彈出層以外的其餘地方須要隱藏該彈出層。node

基礎html代碼:ios

<div>
    <ul class="press-operation">
        <li>複製</li>
        <li>撤回</li>
    </ul>
    <div @touchstart="keepPress($event)" @touchmove="" @touchend="keepPressEnd($event)" @touchcancel="">
        <img class="img" src="" />
    </div>
</div>

複製代碼

需求實現:

// 經過定時器,只有長按超過500ms是才進行須要的操做
    // 按下時觸發
    keepPress(event){
        let nodeEl = event.currentTarget.parentElement.firstElementChild
        this.pressTimer = setInterval(() => {
          nodeEl.style.display = 'block'
        },500)
    }
    // 鬆開時觸發
    keepPressEnd(event){
        clearInterval(this.pressTimer)
      },
      
    // 點擊彈出層其餘地方關閉彈出層
    document.addEventListener('click',function () {
        $('.press-operation').hide()
      })
複製代碼

問題一:

在安卓中,上面的代碼能實現咱們的需求,可是,在IOS中,長按鬆開後,彈出層就立馬關閉了!!!dom

瞭解了下touch和click事件:ide

touchstart:ui

  • touchstart 手指觸碰開始就能觸發

click:this

  • 1.手指觸碰
  • 2.手指未在屏幕上移動
  • 3.在這個dom上手指離開屏幕
  • 4.觸摸和離開屏幕之間的時間間隔較短

上網一頓搜索發現touch和click的執行順序:spa

touchstart --> touchmove --> touchend --> touchcancel --> clickcode

因此,執行完touch事件後會執行click事件,在ios中就會出現長按鬆開後就會關閉彈出層。這裏咱們須要阻止touch事件的默認行爲使用event.preventDefault()htm

修改下==keepPress==中的代碼

keepPress(event){
        event.preventDefault()  // <==添加了這句
        let nodeEl = event.currentTarget.parentElement.firstElementChild
        this.pressTimer = setInterval(() => {
          nodeEl.style.display = 'block'
        },500)
    }

複製代碼

這樣代碼就能知足咱們的需求了。

問題二:

當咱們發送的消息是圖片消息時,咱們須要點擊圖片放大,長按圖片也出現撤銷的彈出層。經過前面的分析,當click和touch事件同時存在時會先觸發touch,再觸發click 。由於咱們阻止了touch事件的默認行爲,因此,咱們點擊圖片的時候並不會觸發click事件,圖片也就不會放大。

這裏咱們須要在==touchend==中作處理,若是長按時間短,就用代碼觸發圖片的點擊事件,長按時間長,就不觸發圖片的點擊事件。

修改前面的代碼:

keepPress(event){
       event.preventDefault()
       this.pressTime = 0 // 清0計數器
       $('.press-operation').hide() // 每次長按會先隱藏全部的彈出層
       let nodeEl = event.currentTarget.parentElement.firstElementChild
       this.pressTimer = setInterval(() => {
         this.pressTime = this.pressTime + 1
           nodeEl.style.display = 'block'
       },500)
     },
     keepPressEnd(event){
       let el = event.currentTarget.getElementsByClassName('img')[0]
       clearInterval(this.pressTimer)
       if(this.pressTime < 1){ // 長按時間不足500ms時,觸發點擊事件
         if(el){
           el.click()
         }

       }
     },
複製代碼

到此爲止,應該是知足了個人需求了

感謝您的閱讀

若有不對,歡迎指正。若有其餘實現方法,歡迎留言討論~

相關文章
相關標籤/搜索