首頁 web前端 js教程 Vue使用Sortable步驟詳解

Vue使用Sortable步驟詳解

May 02, 2018 am 10:32 AM
步驟 詳解

這次帶給大家Vue使用Sortable步驟詳解,Vue使用Sortable的注意事項有哪些,以下就是實戰案例,一起來看一下。

之前開發一個後台管理系統,裡面用到了Vue和Element-UI這個元件庫,遇到一個蠻有意思的問題,跟大家分享一下。

場景是這樣,在一個清單展示頁上,我使用了Element-UI的表格元件,新的需求是在原始表格的基礎上支援拖曳排序。但是原有的元件本身不支援拖曳排序,而且由於是直接引入的Element-UI,不方便修改它的原始碼,所以比較可行的方法只能是直接操作DOM。

具體的做法是在mounted生命週期函數裡,對this.$el進行真實DOM的操作,監聽drag的一系列事件,在事件回調裡移動DOM,並更新data。

HTML5 Drag事件還是挺多的,和Touch事件差不多,自己手工實現也可以,不過這裡就偷了個懶,直接用了一個開源的Sortable庫,直接傳入this.$el,監聽封裝後的回調,並且根據Vue的開發模式,在行動DOM的回呼裡更新實際的Data數據,保持數據和DOM的一致性。

如果你以為到這就結束了,那就大錯特錯,偷過的懶遲早要還。 。 。本來以為這個方案是很美好的,沒想到剛想調試一下,就出現了詭異的現象:A和B拖曳交換位置之後,B和A又神奇得換回去了!這是怎麼回事?似乎我們的操作沒有什麼問題,在真實DOM移動了之後,我們也移動了對應的data,資料數組的順序和渲染出DOM的順序應該是一致的。

問題出在哪裡?我們回想Vue的實作原理,在Vue2.0之前是透過defineProperty依賴注入和追蹤的方式實現雙向綁定。針對v-for數組指令,如果指定了唯一的Key,則會透過高效率的Diff演算法計算出數組內元素的差異,進行最少的移動或刪除操作。而Vue2.0之後在引入了Virtual Dom之後,Children元素的Dom Diff演算法和前者其實是相似的,唯一的差別就是,2.0之前Diff直接針對v-for指令的數組對象,2.0之後則是針對Virtual Dom。 DOM Diff演算法在這裡不再贅述,這裡解釋的比較清楚virtual-dom diff演算法

#假設我們的列表元素數組是

['A','B', 'C','D']

渲染出來後的DOM節點

[$A,$B,$C,$ D]

那麼Virtual Dom對應的結構就是

[{elm:$A,data:'A'},
 {elm:$B, data:'B'},
 {elm:$C,data:'C'},
 {elm:$D,data:'D'}]

##假設拖拽排序之後,真實的DOM變成

[$B,$A,$C,$D]

此時我們只操作了真實DOM,改編了它的位置,而Virtual Dom的結構並沒有改變,依然是

[{elm:$A,data:'A'},

 {elm:$B,data: 'B'},
 {elm:$C,data:'C'},
 {elm:$D,data:'D'}]

此時我們把列表元素也依照真實DOM排序後變成

['B','A','C','D']

這時候根據Diff演算法,計算出的Patch為,VNode前兩項是同類型的節點,所以直接更新,也就是把$A節點更新成$B,把$B節點更新成$A,真實DOM又變回了

[$A,$B,$C,$D]

所以就出現了拖曳之後又被Patch演算法更新了一次的問題,操作路徑可以簡單理解為

拖曳移動真實DOM -> 操作資料數組-> Patch演算法再更新真實DOM

根本原因

根本原因是Virtual DOM和真實DOM之間出現了不一致。

所以在Vue2.0以前,因為沒有引進Virtual DOM,這個問題是不存在的。

在使用Vue框架的時候要盡量避免直接操作DOM

解決方案

1、透過設定key唯一標誌每一個VNode,這也是Vue推薦的使用v-for指令的方式。因為在判斷兩個VNode是否為相同類型時會呼叫sameVnode方法,優先判斷key是否相同

function sameVnode (a, b) {
 return (
  a.key === b.key &&
  a.tag === b.tag &&
  a.isComment === b.isComment &&
  isDef(a.data) === isDef(b.data) &&
  sameInputType(a, b)
 )
}
登入後複製

2、因為根本原因是真實DOM和VNode不一致,所以可以透過把拖曳移動真實DOM的運算還原,即在回呼函數裡,把[$B,$A,$C,$D]還原成[$A,$B,$C,$D],讓DOM的運算交還給Vue

拖曳移動真實DOM ->還原移動操作-> 操作資料數組-> Patch演算法再更新真實DOM

程式碼如下

var app = new Vue({
    el: '#app', 
    mounted:function(){
      var $ul = this.$el.querySelector('#ul')
      var that = this
      new Sortable($ul, {
        onUpdate:function(event){
          var newIndex = event.newIndex,
            oldIndex = event.oldIndex
            $li = $ul.children[newIndex],
            $oldLi = $ul.children[oldIndex]
          // 先删除移动的节点
          $ul.removeChild($li)  
          // 再插入移动的节点到原有节点,还原了移动的操作
          if(newIndex > oldIndex) {
            $ul.insertBefore($li,$oldLi)
          } else {
            $ul.insertBefore($li,$oldLi.nextSibling)
          }
          // 更新items数组
          var item = that.items.splice(oldIndex,1)
          that.items.splice(newIndex,0,item[0])
          // 下一个tick就会走patch更新
        }
      })
    },
    data:function() {
      return {
        message: 'Hello Vue!',
        items:[{
          key:'1',
          name:'1'
        },{
          key:'2',
          name:'2'
        },{
          key:'3',
          name:'3'
        },{
          key:'4',
          name:'4'
        }]
      }
    },
    watch:{
      items:function(){
        console.log(this.items.map(item => item.name))
      }
    }
  })
登入後複製

3 .暴力解決!不走patch更新,透過v-if設置,直接重新渲染一遍。當然不建議這麼做,只是提供這種思路~

    mounted:function(){
      var $ul = this.$el.querySelector('#ul')
      var that = this
      var updateFunc = function(event){
        var newIndex = event.newIndex,
          oldIndex = event.oldIndex
        var item = that.items.splice(oldIndex,1)
        that.items.splice(newIndex,0,item[0])
        // 暴力重新渲染!
        that.reRender = false
        // 借助nextTick和v-if重新渲染
        that.$nextTick(function(){
          that.reRender = true
          that.$nextTick(function(){
            // 重新渲染之后,重新进行Sortable绑定
            new Sortable(that.$el.querySelector('#ul'), {
              onUpdate:updateFunc
            })
          })
        })
      }
      new Sortable($ul, {
        onUpdate:updateFunc
      })
    },
登入後複製

相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!

推薦閱讀:

vue-cli怎樣做出跨網域請求

Angular5對元件標籤新增樣式class步驟說明

JS怎麼實作運算子重載

以上是Vue使用Sortable步驟詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
如何在iPhone中使Google地圖成為預設地圖 如何在iPhone中使Google地圖成為預設地圖 Apr 17, 2024 pm 07:34 PM

iPhone上的預設地圖是Apple專有的地理位置供應商「地圖」。儘管地圖越來越好,但它在美國以外的地區運作不佳。與谷歌地圖相比,它沒有什麼可提供的。在本文中,我們討論了使用Google地圖成為iPhone上的預設地圖的可行性步驟。如何在iPhone中使Google地圖成為預設地圖將Google地圖設定為手機上的預設地圖應用程式比您想像的要容易。請依照以下步驟操作–先決條件步驟–您必須在手機上安裝Gmail。步驟1–開啟AppStore。步驟2–搜尋“Gmail”。步驟3–點選Gmail應用程式旁

升級微信最新版本的步驟(輕鬆掌握微信最新版本的升級方法) 升級微信最新版本的步驟(輕鬆掌握微信最新版本的升級方法) Jun 01, 2024 pm 10:24 PM

不斷推出新版本以提供更好的使用體驗,微信作為中國的社交媒體平台之一。升級微信至最新版本是非常重要的,家人和同事的聯繫、為了保持與朋友、及時了解最新動態。 1.了解最新版本的特性與改進了解最新版本的特性與改進非常重要,在升級微信之前。效能改進和錯誤修復,透過查看微信官方網站或應用程式商店中的更新說明、你可以了解新版本所帶來的各種新功能。 2.檢查目前微信版本我們需要檢查目前手機上已安裝的微信版本、在升級微信之前。點擊,打開微信應用“我”然後選擇,菜單“關於”在這裡你可以看到當前微信的版本號,。 3.打開應

此 Apple ID 尚未在 iTunes Store 中使用:修復 此 Apple ID 尚未在 iTunes Store 中使用:修復 Jun 10, 2024 pm 05:42 PM

使用AppleID登入iTunesStore時,可能會在螢幕上拋出此錯誤提示「此AppleID尚未在iTunesStore中使用」。沒有什麼可擔心的錯誤提示,您可以按照這些解決方案集進行修復。修正1–更改送貨地址此提示出現在iTunesStore中的主要原因是您的AppleID個人資料中沒有正確的地址。步驟1–首先,開啟iPhone上的iPhone設定。步驟2–AppleID應位於所有其他設定的頂部。所以,打開它。步驟3–在那裡,打開“付款和運輸”選項。步驟4–使用面容ID驗證您的存取權限。步驟

Shazam應用程式在iPhone中無法運作:修復 Shazam應用程式在iPhone中無法運作:修復 Jun 08, 2024 pm 12:36 PM

iPhone上的Shazam應用程式有問題? Shazam可協助您透過聆聽歌曲找到歌曲。但是,如果Shazam無法正常工作或無法識別歌曲,則必須手動對其進行故障排除。修復Shazam應用程式不會花費很長時間。因此,無需再浪費時間,請按照以下步驟解決Shazam應用程式的問題。修正1–禁用粗體文字功能iPhone上的粗體文字可能是Shazam無法正常運作的原因。步驟1–您只能從iPhone設定執行此操作。所以,打開它。步驟2–接下來,開啟其中的「顯示和亮度」設定。步驟3–如果您發現啟用了“粗體文本

iPhone螢幕截圖不起作用:如何修復 iPhone螢幕截圖不起作用:如何修復 May 03, 2024 pm 09:16 PM

螢幕截圖功能在您的iPhone上不起作用嗎?截圖非常簡單,因為您只需同時按住「提高音量」按鈕和「電源」按鈕即可抓取手機螢幕。但是,還有其他方法可以在設備上捕獲幀。修復1–使用輔助觸控使用輔助觸控功能截取螢幕截圖。步驟1–轉到您的手機設定。步驟2–接下來,點選以開啟「輔助功能」設定。步驟3–開啟「觸摸」設定。步驟4–接下來,開啟「輔助觸控」設定。步驟5–打開手機上的「輔助觸控」。步驟6–打開“自訂頂級選單”以存取它。步驟7–現在,您只需將這些功能中的任何一個連結到螢幕擷取即可。因此,點擊那裡的首

iPhone中缺少時鐘應用程式:如何修復 iPhone中缺少時鐘應用程式:如何修復 May 03, 2024 pm 09:19 PM

您的手機中缺少時鐘應用程式嗎?日期和時間仍將顯示在iPhone的狀態列上。但是,如果沒有時鐘應用程序,您將無法使用世界時鐘、碼錶、鬧鐘等多項功能。因此,修復時鐘應用程式的缺失應該是您的待辦事項清單的首位。這些解決方案可以幫助您解決此問題。修復1–放置時鐘應用程式如果您錯誤地從主畫面中刪除了時鐘應用程序,您可以將時鐘應用程式放回原位。步驟1–解鎖iPhone並開始向左側滑動,直到到達「應用程式庫」頁面。步驟2–接下來,在搜尋框中搜尋「時鐘」。步驟3–當您在搜尋結果中看到下方的「時鐘」時,請按住它並

Win11系統管理員權限取得步驟詳解 Win11系統管理員權限取得步驟詳解 Mar 08, 2024 pm 09:09 PM

Windows11作為微軟最新推出的作業系統,深受廣大用戶喜愛。在使用Windows11的過程中,有時候我們需要取得系統管理員權限,以便進行一些需要權限的操作。接下來將詳細介紹在Windows11中取得系統管理員權限的步驟。第一步,點擊“開始功能表”,在左下角可以看到Windows圖標,點擊該圖標即可開啟“開始功能表”。第二步,在「開始功能表」中尋找並點擊「

WiFi通話在iPhone上不起作用:修復 WiFi通話在iPhone上不起作用:修復 Jun 03, 2024 am 11:16 AM

無法在iPhone上啟用Wi-Fi通話?通話品質得到改善,您甚至可以從蜂窩網路不那麼強大的遠端位置進行通訊。 Wi-Fi通話也提高了標準通話和視訊通話品質。因此,如果您無法使用手機上的Wi-Fi通話,這些解決方案可能會幫助您解決問題。修復1–手動啟用Wi-Fi通話您必須在iPhone設定中啟用Wi-Fi通話功能。步驟1–為此,您必須打開“設定”。步驟2–接下來,只需向下找到並開啟「電話」設定即可步驟3–在電話設定中,向下捲動並開啟「Wi-Fi通話」設定。步驟4–在Wi-Fi通話頁面中,將「此iPh

See all articles