【實戰技巧】VUE3.0實現簡易的可拖放列表排序

項目地址

項目地址👉👉點擊進入,能夠直接設置爲瀏覽器主頁或者桌面快捷方式進行使用,本人在用,長期維護。javascript

源碼地址

徹底開源,你們能夠隨意研究,二次開發。固然仍是十分歡迎你們點個Star⭐⭐⭐
👉👉源碼連接(gitee)       👉👉源碼連接(github)vue

需求介紹

上面是我一個開源的用來收藏網站的小項目,可是現階段只能一個一個的按順序添加網址,這樣就產生了一個問題,那就是後添加的必定在下面,而我若是新添加了一個比較經常使用的網站,而列表又過長的話,每次進入都須要翻到下面去找,實在是太不方便。java

因此我就想添加一個拖拽排序的功能,在編輯模式下,能夠經過拖拽圖標進行排序,退出編輯模式自動保存,這樣就解決了上面的問題,優化了用戶體驗。react

下面就詳細記錄一下此功能的實現。git

HTML拖放接口

首先仍是先學習一下APIgithub

官方介紹

HTML 拖放(Drag and Drop)接口使應用程序可以在瀏覽器中使用拖放功能。例如,用戶可以使用鼠標選擇可拖拽(draggable)元素,將元素拖拽到可放置(droppable)元素,並釋放鼠標按鈕以放置這些元素。拖拽操做期間,會有一個可拖拽元素的半透明快照跟隨着鼠標指針。數組

拖拽事件

可用的拖拽事件一共有七個,其中三個是用於拖拽元素瀏覽器

  • dragstart 在元素開始被拖動時觸發
  • dragend 在拖動操做完成時觸發
  • drag 在元素被拖動時觸發

四個是用於釋放區域服務器

  • dragenter 當被拖動元素進入到釋放區所佔據的屏幕空間時觸發
  • dragover 當被拖動元素在釋放區內移動時觸發
  • dragleave 當被拖動元素沒有放下就離開釋放區時觸發
  • drop 當被拖動元素在釋放區裏放下時觸發

步驟

  • 首先給被拖放的元素添加 draggable 屬性並添加 dragstart 事件處理函數
  • 定義拖放數據,本例定義的是拖拽元素的id
  • 定義一個釋放區域,添加 dropdragover 事件處理函數,並阻止默認事件
  • 處理拖放數據
  • 拖放結束,添加 dragend 事件處理函數

例子

16 (1).gif

代碼

<body>
  <div class="box" id='box1'> <div id="child" draggable="true"></div> </div>
  <div class="box" id='box2'> </div>
</body>
<script> ((doc) => { const box1 = doc.querySelector("#box1") const box2 = doc.querySelector("#box2") const child = doc.querySelector("#child") // 綁定事件函數 const bindEvents = () => { child.addEventListener("drag", handleDrag) child.addEventListener("dragstart", handleDragstart) child.addEventListener("dragend", handleDragend) box2.addEventListener("dragenter", handleDragenter) box2.addEventListener("dragover", handleDragover) box2.addEventListener("dragleave", handleDragleave) box2.addEventListener("drop", handleDrop) }; // 在元素被拖動時觸發 const handleDrag = (ev) => { console.log('🚀🚀 ~ drag 觸發啦'); } // 在元素開始被拖動時觸發 const handleDragstart = (ev) => { console.log('🚀🚀 ~ dragstart 觸發啦'); ev.dataTransfer.setData('id', ev.target.id); } // 在拖動操做完成時觸發 const handleDragend = (ev) => { console.log('🚀🚀 ~ dragend 觸發啦'); } // 當被拖動元素進入到釋放區所佔據的屏幕空間時觸發 const handleDragenter = (ev) => { console.log('🚀🚀 ~ dragenter 觸發啦'); } // 當被拖動元素在釋放區內移動時觸發 const handleDragover = (ev) => { ev.preventDefault(); console.log('🚀🚀 ~ dragover 觸發啦'); } // 當被拖動元素沒有放下就離開釋放區時觸發 const handleDragleave = (ev) => { console.log('🚀🚀 ~ dragleave 觸發啦'); } // 當被拖動元素在釋放區裏放下時觸發 const handleDrop = (ev) => { console.log('🚀🚀 ~ drop 觸發啦'); ev.preventDefault(); const data = ev.dataTransfer.getData("id"); ev.target.appendChild(document.getElementById(data)); } // 初始化函數 const init = () => { bindEvents(); }; // 執行初始化函數 init(); })(document); </script>
複製代碼

在VUE3中的實現思路

原生js實現拖拽排序我尚未弄,可是在vue中就很是的簡單,由於咱們在觸發任何事件的時候,均可以拿到元素的index,咱們能夠靠index輕易實現。markdown

  • dragstart中記錄下舊的索引
  • dragover中記錄下新的索引,每次通過一個都會更新
  • drop事件中處理數組,刪掉舊的元素,在目標索引添加新的元素
//簡略後的僞代碼 詳情請查看源碼
<div draggable="true" v-for='(item,index) in markList' :key='index' 
@dragstart="handleDragstart(index)" 
@drop.prevent="handleDrop()"
@dragover.prevent="handleDragover(index)">
</div>


//js
const state = reactive<MarkState>({
  // 當前正在拖拽的元素索引
  oldItemIndex: -1,
  // 將插入的目標位置索引
  newItemIndex: -1,
});
// 開始拖拽時觸發
const handleDragstart = (index: number) => {
  state.oldItemIndex = index;
};
// 中止拖拽時觸發
const handleDrop = () => {
  // 若是位置沒有發生改變 什麼也不作
  if (state.newItemIndex === state.oldItemIndex) {
    return;
  }
  // 若是位置發生了改變
  emit('change-mark-index', state.oldItemIndex, state.newItemIndex);
};
// 拖拽通過其餘元素時觸發
const handleDragover = (index: number) => {
  state.newItemIndex = index;
};


//change-mark-index
// 修改書籤索引
const changeMarkIndex = (oldItemIndex: number, newItemIndex: number) => {
  // 刪除老的
  const changeItem = marks.value.splice(oldItemIndex, 1)[0];
  // 在列表中目標位置增長新的
  marks.value.splice(newItemIndex, 0, changeItem);
};
複製代碼

最終實現

16.gif

接下來的開發計劃

💡拖拽到目標位置後會有位置提示

💡支持拖拽到其餘標籤下

💡添加拖拽動畫

拖拽動畫這裏我試了vue內部的 transition-group 可是沒有成功,若是你們有什麼思路或者建議,請你們不吝賜教,在下方評論或者私信我,十分感謝🙏🙏🙏.

最後感謝各位的耐心觀看,既然都到這了,點個 👍贊再走吧

連接整合

🔊項目預覽地址(GitHub Pages):👉👉alanhzw.github.io

🔊項目預覽備用地址(本身的服務器):👉👉warbler.duwanyu.com

🔊源碼地址(gitee):👉👉gitee.com/hzw_0174/wa…

🔊源碼地址(github):👉👉github.com/alanhzw/War…

🔊個人博客:👉👉www.duwanyu.com

相關文章
相關標籤/搜索