Vue Draggable實(shí)現(xiàn)拖拽功能的操作方法
這是一個(gè)關(guān)于 vuedraggable 的非常詳盡的指南,涵蓋了如何使用它,以及它幾乎所有的屬性、事件、插槽和方法。
vuedraggable 是一個(gè)基于強(qiáng)大的 Sortable.js 庫(kù)的 Vue 組件,它允許你通過(guò)拖拽的方式對(duì)列表進(jìn)行排序、移動(dòng)、克隆等操作,并且與 Vue 的數(shù)據(jù)響應(yīng)式系統(tǒng)無(wú)縫集成。
1. VueDraggable 的核心概念
- 數(shù)據(jù)驅(qū)動(dòng): 你只需要管理一個(gè)數(shù)組數(shù)據(jù),
vuedraggable會(huì)自動(dòng)處理 DOM 的移動(dòng)和更新。 - 基于 Sortable.js: 它繼承了
Sortable.js的所有強(qiáng)大功能和配置選項(xiàng)。 - 組件化: 以 Vue 組件的形式使用,非常易于集成。
2. 如何安裝和使用
A. 安裝
對(duì)于 Vue 3 (推薦)
你需要安裝 vuedraggable@next 版本。
npm install vuedraggable@next
對(duì)于 Vue 2
使用默認(rèn)版本即可。
npm install vuedraggable
本指南將主要以 Vue 3 的 vuedraggable@next 為例,因?yàn)樗砹宋磥?lái)的方向。
B. 基本用法
下面是一個(gè)最簡(jiǎn)單的例子,展示了如何在一個(gè)列表中進(jìn)行拖拽排序。
<template>
<div>
<h3>可拖拽列表</h3>
<draggable
v-model="myList"
item-key="id"
@start="onStart"
@end="onEnd"
>
<template #item="{element, index}">
<div class="list-item">
{{ element.name }} (ID: {{ element.id }}) - 索引: {{ index }}
</div>
</template>
</draggable>
<pre>{{ JSON.stringify(myList, null, 2) }}</pre>
</div>
</template>
<script setup>
import { ref } from 'vue';
import draggable from 'vuedraggable';
const myList = ref([
{ id: 1, name: '蘋果' },
{ id: 2, name: '香蕉' },
{ id: 3, name: '橘子' },
{ id: 4, name: '葡萄' }
]);
const onStart = (event) => {
console.log('拖拽開始', event);
};
const onEnd = (event) => {
console.log('拖拽結(jié)束', event);
// event.oldIndex - 拖拽前的位置
// event.newIndex - 拖拽后的位置
console.log(`從索引 ${event.oldIndex} 移動(dòng)到 ${event.newIndex}`);
};
</script>
<style scoped>
.list-item {
padding: 10px;
margin: 5px;
background-color: #f0f0f0;
border: 1px solid #ccc;
cursor: grab;
}
.list-item:active {
cursor: grabbing;
}
</style>核心解釋:
import draggable from 'vuedraggable': 引入組件。<draggable>: 這是vuedraggable的組件標(biāo)簽。v-model="myList": 這是最關(guān)鍵的部分。它將組件與你的數(shù)據(jù)數(shù)組myList雙向綁定。當(dāng)你在界面上拖拽排序后,myList數(shù)組的順序會(huì)自動(dòng)更新。item-key="id": 極其重要! 為了讓 Vue 能夠高效地跟蹤和復(fù)用每個(gè)列表項(xiàng),你需要提供一個(gè)唯一的key。它可以是一個(gè)字符串,指向你數(shù)組對(duì)象中唯一的屬性(如id),或者是一個(gè)返回唯一值的函數(shù)。#item="{element, index}": 這是默認(rèn)插槽的用法。vuedraggable會(huì)遍歷你的v-model數(shù)組,并為每一項(xiàng)提供element(當(dāng)前項(xiàng)的數(shù)據(jù)) 和index(當(dāng)前項(xiàng)的索引) 作為插槽 prop,供你在模板中使用。
C. 兩個(gè)列表之間拖拽
這是另一個(gè)常見場(chǎng)景,例如從一個(gè)"待辦事項(xiàng)"列表拖到"已完成"列表。
<template>
<div class="two-lists">
<div>
<h3>待辦事項(xiàng)</h3>
<draggable
v-model="list1"
item-key="id"
group="tasks"
class="list-group"
>
<template #item="{element}">
<div class="list-group-item">{{ element.name }}</div>
</template>
</draggable>
</div>
<div>
<h3>已完成</h3>
<draggable
v-model="list2"
item-key="id"
group="tasks"
class="list-group"
>
<template #item="{element}">
<div class="list-group-item">{{ element.name }}</div>
</template>
</draggable>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import draggable from 'vuedraggable';
const list1 = ref([
{ id: 1, name: '寫代碼' },
{ id: 2, name: '測(cè)試功能' },
]);
const list2 = ref([
{ id: 3, name: '修復(fù)Bug' },
{ id: 4, name: '上線發(fā)布' },
]);
</script>
<style>
.two-lists { display: flex; gap: 20px; }
.list-group { min-height: 100px; background-color: #eee; padding: 10px; }
.list-group-item { padding: 10px; background-color: white; border: 1px solid #ddd; margin-bottom: 5px; cursor: grab; }
</style>核心解釋:
group="tasks": 兩個(gè)draggable組件設(shè)置了相同的group名稱。這告訴vuedraggable,它們屬于同一個(gè)組,元素可以在它們之間相互拖拽。
3. 所有屬性 (Props)
vuedraggable 的屬性主要分為兩類:組件自身屬性和繼承自 Sortable.js 的選項(xiàng)。
A. 組件核心屬性
| 屬性名 | 類型 | 默認(rèn)值 | 描述 |
|---|---|---|---|
v-model | Array | [] | 必需。用于雙向綁定的數(shù)據(jù)數(shù)組。當(dāng)拖拽操作完成時(shí),此數(shù)組會(huì)自動(dòng)更新。 |
item-key | String | Function | - | 必需。用于 Vue diff 算法的唯一標(biāo)識(shí)??梢允菍?duì)象中的屬性名(如 'id')或一個(gè)返回唯一值的函數(shù) (element) => element.id。 |
tag | String | 'div' | 指定 draggable 組件渲染的根元素標(biāo)簽,例如 'ul', 'tbody' 等。 |
componentData | Object | {} | 一個(gè)對(duì)象,用于向渲染的根元素(由 tag 決定)傳遞額外的 HTML 屬性,如 class, style, id 等。 |
B. 繼承自 Sortable.js 的選項(xiàng) (作為 Props 使用)
這些屬性直接控制拖拽的行為,非常強(qiáng)大。
| 屬性名 | 類型 | 默認(rèn)值 | 描述 |
|---|---|---|---|
group | String | Object | undefined | 用于在多個(gè)列表之間拖拽。設(shè)置為相同字符串名的列表可以互相拖拽。也可以是對(duì)象 { name: 'my-group', pull: true, put: true, pull: 'clone' } 來(lái)進(jìn)行更精細(xì)的控制。 |
sort | Boolean | true | 是否允許在列表內(nèi)部進(jìn)行排序。 |
disabled | Boolean | false | 是否禁用整個(gè) draggable 組件。 |
animation | Number | 150 | 拖拽動(dòng)畫的持續(xù)時(shí)間(毫秒)。設(shè)置為 0 則禁用動(dòng)畫。 |
handle | String | undefined | 指定一個(gè) CSS 選擇器(如 .drag-handle),只有拖拽這個(gè)選擇器匹配的元素才能觸發(fā)拖拽。 |
filter | String | undefined | 指定一個(gè) CSS 選擇器,該選擇器匹配的元素將不能被拖拽(例如,輸入框)。 |
ghostClass | String | 'sortable-ghost' | 拖拽時(shí),元素在目標(biāo)位置的占位符的 CSS 類名。 |
chosenClass | String | 'sortable-chosen' | 拖拽時(shí),被選中的源元素的 CSS 類名。 |
dragClass | String | 'sortable-drag' | 拖拽時(shí),正在被拖拽的元素的克隆體的 CSS 類名。 |
forceFallback | Boolean | false | 如果為 true,將強(qiáng)制使用 JS 來(lái)模擬拖拽效果(創(chuàng)建一個(gè)克隆元素),而不是使用原生的 HTML5 拖放 API。在某些復(fù)雜場(chǎng)景或 iframe 中可能需要。 |
fallbackClass | String | 'sortable-fallback' | 當(dāng) forceFallback: true 時(shí),被拖拽的克隆元素的 CSS 類名。 |
fallbackOnBody | Boolean | false | 當(dāng) forceFallback: true 時(shí),是否將克隆元素附加到 document.body。 |
delay | Number | 0 | 鼠標(biāo)按下后需要等待多少毫秒才能開始拖拽。 |
delayOnTouchOnly | Boolean | false | 如果為 true,delay 選項(xiàng)僅在觸摸設(shè)備上生效。 |
touchStartThreshold | Number | 0 | 觸摸設(shè)備上,手指需要移動(dòng)多少像素才能開始拖拽。 |
swapThreshold | Number | 1 | 拖拽元素覆蓋目標(biāo)元素的百分比達(dá)到多少時(shí)才進(jìn)行交換(0 到 1)。 |
invertSwap | Boolean | false | 如果為 true,當(dāng)拖拽元素中心越過(guò)目標(biāo)元素中心時(shí)才進(jìn)行交換。 |
4. 所有事件 (Events)
你可以通過(guò) @event-name 的方式監(jiān)聽這些事件來(lái)執(zhí)行自定義邏輯。
| 事件名 | 載荷 (Payload) | 描述 |
|---|---|---|
start | (event) | 拖拽開始時(shí)觸發(fā)。event 包含 oldIndex。 |
end | (event) | 拖拽結(jié)束時(shí)觸發(fā)。event 包含 oldIndex, newIndex。 |
add | (event) | 當(dāng)元素從另一個(gè)列表拖拽進(jìn)來(lái)時(shí),在新列表上觸發(fā)。event 包含 newIndex。 |
remove | (event) | 當(dāng)元素被拖拽到另一個(gè)列表時(shí),在舊列表上觸發(fā)。event 包含 oldIndex。 |
update | (event) | 當(dāng)列表內(nèi)部排序發(fā)生變化時(shí)觸發(fā)。event 包含 oldIndex, newIndex。 |
choose | (event) | 當(dāng)一個(gè)元素被選中時(shí)觸發(fā)。event 包含 oldIndex。 |
unchoose | (event) | 當(dāng)一個(gè)元素被取消選中時(shí)觸發(fā)。event 包含 oldIndex。 |
sort | (event) | 當(dāng)列表排序發(fā)生任何變化時(shí)觸發(fā)(包括 add, remove, update)。 |
change | (event) | 這是一個(gè)更通用的事件,當(dāng)列表發(fā)生變化時(shí)觸發(fā)。event 對(duì)象包含 added、removed 或 moved 字段,描述了具體的變化。 |
clone | (original) | 當(dāng)使用 pull: 'clone' 時(shí),在克隆元素時(shí)觸發(fā)。original 是原始元素的數(shù)據(jù)。 |
move | (event, originalEvent) | 拖拽過(guò)程中每次移動(dòng)都會(huì)觸發(fā)。可以通過(guò)返回 false 來(lái)取消本次移動(dòng)。 |
5. 所有插槽 (Slots)
| 插槽名 | 作用域變量 ({...}) | 描述 |
|---|---|---|
item | {element, index} | 默認(rèn)插槽。用于渲染列表中的每一個(gè)可拖拽項(xiàng)。element 是當(dāng)前項(xiàng)的數(shù)據(jù)對(duì)象,index 是當(dāng)前項(xiàng)在數(shù)組中的索引。 |
header | - | 在列表的開頭添加一個(gè)固定的、不可拖拽的區(qū)域。 |
footer | - | 在列表的末尾添加一個(gè)固定的、不可拖拽的區(qū)域。 |
插槽示例
<draggable v-model="myList" item-key="id">
<!-- 頭部插槽 -->
<template #header>
<div class="header">這是列表的頭部</div>
</template>
<!-- 默認(rèn)/item 插槽 -->
<template #item="{element}">
<div class="list-item">{{ element.name }}</div>
</template>
<!-- 尾部插槽 -->
<template #footer>
<div class="footer">這是列表的尾部</div>
</template>
</draggable>6. 方法 (Methods)
通常情況下,你不需要直接調(diào)用 vuedraggable 的方法,因?yàn)樗菙?shù)據(jù)驅(qū)動(dòng)的。但在某些特殊情況下,你可能需要通過(guò) ref 訪問(wèn)底層的 Sortable.js 實(shí)例。
給組件添加 ref:
<draggable ref="draggableRef" ...>
在 <script setup> 中定義 ref:
import { ref } from 'vue';
const draggableRef = ref(null);
訪問(wèn) Sortable.js 實(shí)例:vuedraggable 將 Sortable.js 實(shí)例暴露在 sortable 屬性上。
const sortableInstance = draggableRef.value.sortable;
現(xiàn)在你可以調(diào)用 Sortable.js 的原生方法,例如:
sortableInstance.toArray(): 返回一個(gè)包含所有子元素data-id的數(shù)組。sortableInstance.sort(orderArray): 根據(jù)提供的 ID 數(shù)組對(duì)列表進(jìn)行排序。sortableInstance.destroy(): 銷毀 Sortable 實(shí)例。
注意: 直接操作 Sortable.js 實(shí)例可能會(huì)繞過(guò) Vue 的響應(yīng)式系統(tǒng),請(qǐng)謹(jǐn)慎使用。絕大多數(shù)場(chǎng)景都可以通過(guò) props 和 events 來(lái)完成。
總結(jié)
vuedraggable 是一個(gè)功能強(qiáng)大且易于使用的庫(kù)。掌握它的關(guān)鍵在于:
v-model和item-key是基礎(chǔ),必須正確設(shè)置。- 使用
group屬性實(shí)現(xiàn)多列表交互。 - 通過(guò) Props (如
animation,handle,ghostClass) 來(lái)定制拖拽行為和外觀。 - 監(jiān)聽 Events (如
end,add,change) 來(lái)在拖拽操作后執(zhí)行業(yè)務(wù)邏輯(例如,向服務(wù)器發(fā)送更新后的排序)。 - 利用 Slots (
item,header,footer) 來(lái)靈活地定義列表結(jié)構(gòu)。
希望這份詳盡的指南能幫助你完全掌握 vuedraggable!
到此這篇關(guān)于Vue Draggable實(shí)現(xiàn)拖拽功能的文章就介紹到這了,更多相關(guān)Vue Draggable拖拽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- vue使用vuedraggable對(duì)列表進(jìn)行拖拽排序
- vue3中實(shí)現(xiàn)拖拽排序代碼示例(vue-draggable-next的使用)
- vue3使用vuedraggable和grid實(shí)現(xiàn)自定義拖拽布局方式
- vue使用vuedraggable插件實(shí)現(xiàn)拖拽效果
- vuedraggable拖拽到目標(biāo)區(qū)域?qū)崿F(xiàn)過(guò)程解析
- Vue3中使用vuedraggable拖拽實(shí)戰(zhàn)教程
- vue3使用拖拽組件draggable.next的保姆級(jí)教程
- vue-draggable實(shí)現(xiàn)拖拽表單的示例代碼
- vue?draggable組件實(shí)現(xiàn)拖拽及點(diǎn)擊無(wú)效問(wèn)題的解決
相關(guān)文章
Vue3使用element-plus組件不顯示問(wèn)題
這篇文章主要介紹了Vue3使用element-plus組件不顯示問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03
vue實(shí)現(xiàn)PC端錄音功能的實(shí)例代碼
這篇文章主要介紹了vue實(shí)現(xiàn)PC端錄音功能的實(shí)例代碼,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06
使用vue如何構(gòu)建一個(gè)自動(dòng)建站項(xiàng)目
這篇文章主要介紹了使用vue如何構(gòu)建一個(gè)自動(dòng)建站項(xiàng)目,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
Vue動(dòng)態(tài)修改頁(yè)面Title(瀏覽器頁(yè)簽名稱)的三種方法
在開發(fā) Vue 項(xiàng)目時(shí),我們經(jīng)常需要根據(jù)不同的頁(yè)面動(dòng)態(tài)修改瀏覽器的頁(yè)簽標(biāo)題(title),那么,如何在 Vue 項(xiàng)目中實(shí)現(xiàn)動(dòng)態(tài)修改 document.title 呢?本文將介紹三種實(shí)用方法,并結(jié)合代碼示例,助你輕松實(shí)現(xiàn),需要的朋友可以參考下2025-03-03
vue+element+electron仿微信實(shí)現(xiàn)代碼
這篇文章主要介紹了vue+element+electron仿微信實(shí)現(xiàn),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
vue.extend與vue.component的區(qū)別和聯(lián)系
這篇文章主要介紹了vue.extend與vue.component的區(qū)別和聯(lián)系,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2018-09-09
vite+vue3項(xiàng)目解決低版本兼容性問(wèn)題解決方案(Safari白屏)
這篇文章主要介紹了vite+vue3項(xiàng)目解決低版本兼容性問(wèn)題(Safari白屏),使用官方插件 @vitejs/plugin-legacy 為打包后的文件提供傳統(tǒng)瀏覽器兼容性支持,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03
vue跳轉(zhuǎn)頁(yè)面常用的4種方法與區(qū)別小結(jié)
這篇文章主要給大家介紹了關(guān)于vue跳轉(zhuǎn)頁(yè)面常用的4種方法與區(qū)別,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03

