關於 JS 拖拽功能的沖突問題及解決方法


前言

我在之前寫過關於 JS 拖拽的文章,實現方式和網上能搜到的方法大致相同,別無二致,但是在一次偶然的測試中發現,這種綁定事件的方式可能會和其它的拖拽事件產生沖突,由此產生了對於事件綁定的思考。本文主要介紹解決這種沖突的方法,其實就是事件綁定的時機問題。

問題來源

這個問題是在類似如下 CodePen 例子中發現的,在有拖拽功能的頁面中添加一個原生 input range 元素,可以發現 input range 的拖拽失效了。

See the Pen drag with conflict issue by Zongbin (@nzbin) on CodePen.

讓我們看一下拖拽方法代碼:

var draggable = function(modal, handle) {
...
  $(handle).on('mousedown', dragStart);
  $(document).on('mousemove', dragMove);
  $(document).on('mouseup', dragEnd);
}

幾乎網上的大部分拖拽案例都是上面這種綁定事件的方法。起初以為是 jQuery 事件綁定的問題,其實完全不相關,使用原生 JS 同樣會遇到這種問題。

再看一下拖拽的事件綁定,很明顯,在 document 上綁定的事件和 input range 的拖拽事件沖突了。其實,document 作為最上層的節點,它上面不應該綁定其它事件(事件代理除外),如果綁定,必須是臨時性綁定,否則一定會造成沖突。

解決方法

知道問題所在之后,解決方法也非常簡單,其中參考了 jQuery UI 的處理方式。

我們可以在拖拽開始的時候綁定 document 的事件,然后在拖拽結束的時候移除 document 的事件。

var draggable = function(modal, handle) {
...
  var dragStart = function(e) {
...
    $(document).on('mousemove', dragMove)
               .on('mouseup', dragEnd);
  }
...

  var dragEnd = function(e) {
    $(document).off('mousemove')
               .off('mouseup');
...
  }

  $(handle).on('mousedown', dragStart);
  
}

下面 CodePen 中的 input range 已經可以正常拖動了。

See the Pen drag with conflict issue fixed by Zongbin (@nzbin) on CodePen.

總結

我們可以通過控制台的 Event Listener 查看綁定的事件,在平時的工作中,切記不要污染全局的默認事件。一般情況下,工作中並不會遇到本文所說的這一情況,但是如果真的碰到了,需要知道問題的所在。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM