這次帶給大家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+Sortable專案實戰程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。