前端拖拽組件優化

爲何棄用Html5 drag Api

  • 以前我也用的Drag Api寫了一個draggable組件,使用起來總以爲體驗有點很差。
  • 先來看有贊作的相似的拖拽UI組件,它引用的sortablejs庫封裝了Drag Api

圖片描述

  • 一、拖拽的時候跟隨鼠標的影子成爲ghost,是Api自動生成的。可是因爲這是一個很簡潔的頁面,背景全爲白色在拖拽的時候其實很難看出拖到了哪裏。Api雖然提供了e.dataTransfer.setDragImage(img, 0, 0)方法讓咱們在去改變這個ghost,可是設置的這個img必須是HTML img element、HTML canvas element,不然它必須是一個可見的節點。簡單來講就是若是你設置的ghost不是canvas或者img元素,而是你自定義的html元素,那你必須把它append到document中。
document.getElementById("drag-with-create-add").addEventListener("dragstart", function(e) {
        var crt = this.cloneNode(true);
        crt.style.backgroundColor = "red";
        document.body.appendChild(crt);
        e.dataTransfer.setDragImage(crt, 0, 0);
    }, false);
  • 這種方式好像解決了拖拽不明顯的問題,可是設置的ghost是默認有一個透明度的,並且你沒有辦法去改變這個透明度。在上面顯示的這個頁面裏面,即便是cloneNode一個元素出來跟隨鼠標也因爲這個緣由有種不清晰的感受。
  • 二、快速拖拽的時候元素在不停的迴流和重繪

圖片描述

  • 從上圖能夠看到在拖拽排序的時候dom順序不斷在變化,雖說在拖拽的時候頁面已經加載完,這點開銷不會有太大的影響,可是若是可以作到一次拖拽只改變一次dom結構的話固然是最好的。
  • 三、示例的拖拽沒有動畫效果,並且ghost跟隨給人的感受有種很用力才能拖動,有點費勁。這個問題並非吹毛求疵,在稍後優化後的draggable組件動畫可以體現出來。

利用鼠標事件拖拽更流暢

圖片描述

  • 優化以後的拖拽顯然比示例的順暢不少,不會有種吃力拖動的感受。

圖片描述

  • 拖動的過程中,不管怎麼拖動,變化的只是元素的translate,並無引發dom結構的變化,而translate並不會引發迴流和重繪,而是在一次拖拽結束才進行一次更新排序。拖動過程當中也能很明顯地看出當前拖拽的元素。
  • 關於css影響文檔流回流和重繪能夠參考https://docs.google.com/sprea...

優化思路

  • 棄用html5的drag,改用mouse事件
  • mousedown的時候clone當前點擊的元素爲ghost並將原來的元素visibility:hidden;visibility讓原來的元素依然佔據着位置,是拖拽中不改變dom的關鍵。
  • 設置ghost的position爲fixed,脫離文檔流,這樣不管怎麼拖拽都不會影響到佈局。
  • 將mousemove和mouseend事件添加到window上,這樣不管鼠標怎麼移動ghost都流暢跟隨。mousemove的時候判斷ghost與其餘元素的位置,只使用translate去改變,直到真正拖拽結束才進行一次排序。
  • 優化後的自定義ghost能讓人清晰得看到正在移動的元素。

配合vue使用的源碼:https://github.com/sally2015/...,經過v-model輕鬆雙向綁定數據列表css

相關文章
相關標籤/搜索