js如何實現簡單的拖拽排序 列表排序的3種交互實現方法!

實現拖拽排序需監聽dragstart、dragover、drop事件并動態調整dom位置,具體步驟為:1.為列表項添加draggable屬性;2.在dragstart中記錄拖拽元素;3.在dragover中阻止默認行為;4.在drop中根據鼠標位置交換元素位置。性能優化方面可通過requestanimationframe延遲更新、限制拖拽頻率等方式減少重繪重排。交互方式除原生拖拽外還包括上下箭頭按鈕、拖拽手柄和數字輸入框。持久化排序結果可通過獲取排序后的id數組并發送至后端保存,后端更新數據庫中的排序字段即可完成。

js如何實現簡單的拖拽排序 列表排序的3種交互實現方法!

實現拖拽排序,核心在于監聽元素的拖拽事件,并動態調整元素在DOM中的位置。簡單來說,就是抓住、移動、放下。

js如何實現簡單的拖拽排序 列表排序的3種交互實現方法!

解決方案

首先,我們需要為列表項添加 draggable=”true” 屬性,使其可以被拖拽。然后,監聽 dragstart、dragover、drop 這三個關鍵事件。dragstart 記錄開始拖拽的元素,dragover 阻止默認行為,允許元素被放置,drop 則負責實際的元素位置交換。

js如何實現簡單的拖拽排序 列表排序的3種交互實現方法!

<ul id="sortable-list">   <li draggable="true">Item 1</li>   <li draggable="true">Item 2</li>   <li draggable="true">Item 3</li> </ul>  <script>   const list = document.getElementById('sortable-list');   let draggedItem = null;    list.addEventListener('dragstart', (e) => {     draggedItem = e.target;     e.target.classList.add('dragging'); // 可選:添加拖拽樣式   });    list.addEventListener('dragover', (e) => {     e.preventDefault();   });    list.addEventListener('drop', (e) => {     e.preventDefault();     if (e.target.tagName === 'LI' && e.target !== draggedItem) {       const rect = e.target.getBoundingClientRect();       const mouseY = e.clientY;       //判斷鼠標位置是否在目標元素中心之上       if(mouseY < rect.top + rect.height / 2){         list.insertBefore(draggedItem, e.target);       }else{         list.insertBefore(draggedItem, e.target.nextSibling);       }     }     draggedItem.classList.remove('dragging'); // 可選:移除拖拽樣式     draggedItem = null;   });    list.addEventListener('dragend', (e) => {     e.target.classList.remove('dragging');   }); </script>

這段代碼是最基礎的實現。它沒有考慮復雜的邊界情況,也沒有添加視覺反饋。但是,它能讓你快速理解拖拽排序的核心邏輯。

js如何實現簡單的拖拽排序 列表排序的3種交互實現方法!

如何優化拖拽排序的性能,避免頁面卡頓?

拖拽過程中頻繁更新DOM會導致性能問題。一種優化方法是使用 requestAnimationFrame 來延遲DOM更新,減少重繪和重排的次數。另一種方法是使用“虛擬DOM”或者“影子DOM”,先在內存中進行排序,最后一次性更新實際DOM。此外,還可以限制拖拽的頻率,比如使用 throttle 函數。但說實話,對于小型列表,這些優化可能意義不大,甚至適得其反。關鍵在于找到性能瓶頸,針對性地優化。

除了原生拖拽,還有哪些實現列表排序的交互方式?

除了原生拖拽,還可以考慮以下幾種交互方式:

  1. 上下箭頭按鈕: 每個列表項旁邊放置上下箭頭按鈕,點擊按鈕可以上下移動列表項。這種方式簡單直接,但操作效率較低。適合列表項較少,對操作流暢度要求不高的場景。
  2. 拖拽手柄: 在列表項旁邊添加一個拖拽手柄(例如一個小圖標),用戶只能通過拖拽手柄來移動列表項。這種方式可以避免誤操作,提高用戶體驗。實現上,只需要將拖拽事件綁定到拖拽手柄上即可。
  3. 數字輸入框: 在列表項旁邊添加一個數字輸入框,用戶可以直接輸入列表項的目標位置。這種方式適合列表項非常多,需要精確排序的場景。但用戶體驗相對較差,需要額外的驗證和提示。

選擇哪種交互方式,取決于具體的應用場景和用戶需求。沒有最好的方案,只有最合適的方案。

如何持久化拖拽排序后的結果,例如保存到數據庫?

最簡單的方法是獲取排序后的列表項的ID數組,然后將這個數組保存到數據庫。例如:

const sortedIds = Array.from(list.children).map(item => item.id); // 將 sortedIds 發送到后端保存 fetch('/save-order', {   method: 'POST',   headers: {     'Content-Type': 'application/JSon'   },   body: JSON.stringify({ order: sortedIds }) }) .then(response => response.json()) .then(data => {   console.log('保存成功', data); });

后端接收到ID數組后,需要更新數據庫中對應記錄的排序字段。這個排序字段可以是整數,也可以是字符串。關鍵在于保持排序字段的一致性,方便后續查詢和展示。當然,如果數據量非常大,可能需要考慮更復雜的排序算法和數據庫優化方案,例如使用 redis 等緩存數據庫。但對于大多數應用來說,這種簡單的方案已經足夠了。

? 版權聲明
THE END
喜歡就支持一下吧
點贊14 分享