官方文档:https://www.npmjs.com/package/vuedraggable
中文文档:http://www.itxst.com/vue-draggable/tutorial.html
案例下载地址:
https://github.com/SortableJS/Vue.Draggable.git
vuedraggablehttps://sortablejs.github.io/Vue.Draggable/#/functional
安装:
npm install vuedraggable
yarn add vuedraggable
<!-- 两个表拖拽 -->
<template>
<div>表1</div>
<draggable
:list="list1"
item-key="id"
tag="div"
:group="{ name: 'content', pull: 'clone', put: false }"
animation="300"
>
<template #item="{ element }">
<div class="cursor-pointer" :id="element.id">{{ element.name }}</div>
</template>
</draggable>
<div>input增加</div>
<div class="row items-center">
<input type="text" v-model="listInput" />
<div @click="onAdd()">增加</div>
</div>
<div>表2</div>
<draggable
:list="list2"
item-key="id"
tag="div"
group="content"
animation="300"
@change="renewPreview"
>
<template #item="{ element }">
<div>
<div class="relative-position">{{ element.name }}</div>
<div @click="onDelete(element)">删除</div>
</div>
</template>
</draggable>
<div v-model="preview"></div>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue';
import { $useApi } from 'boot/index';
import { v4 as uuidv4 } from 'uuid';
import draggable from 'vuedraggable';
const list1 = ref([]);
const list2 = ref([]);
const listInput = ref(null);
const searchList = ref(null);
const preview = ref(null);
// 删除
const onDelete = (str) => {
list2.value = list2.value.filter((t) => t.id != str.id);
renewPreview();
};
// 增加input内容
const onAdd = () => {
list2.value.push({
id: 'aaa-' + uuidv4(),
name: listInput.value,
});
renewPreview();
listInput.value = '';
};
// 更新内容
const renewPreview = () => {
let pContent = '';
list2.value.forEach((t) => {
if (t.id.indexOf('aaa') !== -1) {
pContent += t.name;
} else {
pContent += 'XXX';
}
});
preview.value = pContent;
};
// 搜索
watch(
() => searchList.value,
(newValue) => {
getListInfo(newValue);
}
);
onMounted(() => {
getInfo();
getListInfo();
});
// 获取元数据项信息
const getListInfo = async (str) => {
const { data } = await $useApi.get('/xxx', {
params: {
name: str,
},
});
list1.value = uniqueItems(data);
};
// 数据去重
const uniqueItems = (data) => {
// 合并重复name数据
let arr = [];
data.forEach((x) => {
let map = arr.find((y) => y.name === x.name);
if (map) {
map.ids.push(x.id);
} else {
x.ids = [x.id];
arr.push(x);
}
});
return arr;
};
// 基本信息
const getInfo = async () => {
const { data } = await $useApi.get('/xxx');
if (data) {
list2.value = data?.nameMap ?? [];
}
};
</script>
属性:
group: { name: "...", pull: [true, false, clone],
tag: 'td' // 默认div,设置draggable标签解析html标签
v-model:data // 绑定数据列表
put: [true, false, array] } //name相同的组可以互相拖动, pull可以写条件判断,是否允许拖走,put可以写条件判断,是否允许拖入
sort: true, // 内部拖动排序列表
delay: 0, // 以毫秒为单位定义排序何时开始。
touchStartThreshold: 0, // px,在取消延迟拖动事件之前,点应该移动多少像素?
disabled: false, // 如果设置为真,则禁用sortable。
animation: 150, // ms, 动画速度运动项目排序时,' 0 ' -没有动画。
handle: ".my-handle", // 在列表项中拖动句柄选择器,设置某些地方拖动才有效。
filter: ".ignore-elements", // 不能拖拽的选择器(字符串 class)
preventOnFilter: true, // 调用“event.preventDefault()”时触发“filter”
draggable: ".item", // 指定元素中的哪些项应该是可拖动的class。
ghostClass: "sortable-ghost", // 设置拖动元素的class的占位符的类名。
chosenClass: "sortable-chosen", // 设置被选中的元素的class
dragClass: "sortable-drag", //拖动元素的class。
forceFallback: false, // 忽略HTML5的DnD行为,并强制退出。(h5里有个属性也是拖动,这里是为了去掉H5拖动对这个的影响)
fallbackClass: "sortable-fallback", // 使用forceFallback时克隆的DOM元素的类名。
fallbackOnBody: false, // 将克隆的DOM元素添加到文档的主体中。(默认放在被拖动元素的同级)
fallbackTolerance: 0, // 用像素指定鼠标在被视为拖拽之前应该移动的距离。
scroll: true, // or HTMLElement
scrollFn: function(offsetX, offsetY, originalEvent, touchEvt, hoverTargetEl) { ... },
scrollSensitivity: 30, // px
scrollSpeed: 10, // px
事件:
start,add,remove,update,end,choose,unchoose,sort,filter,clone
start (evt) {} // 刚开始拖动时候触发
add (evt) {} // 拖拽新增的时候触发
remove (evt) {} // 从列表拖走,移除触发
update (evt) {} // 列表更新触发
end (evt) {} // 和start对应,拖拽完了触发
choose(evt) {} // 选择拖拽元素触发
sort (evt) {} // 排序触发
change (evt) {} // 这个很重要,如果数据不是整个提交,单个提交数据的时候就会用到它 evt.added.element / evt.removed.element如果这个列表添加元素就会added的数据,如果删除元素就是removed的元素,还会获取到移动和删除的所在位置index
:move (evt, dragevt) {} // 这个也很重要,在两个列表相互拖拽的时候,有时候需要更新ui,在接口还没有更新之前,所以就会用到move,他是把元素从一个列表拖到另一个列表的瞬间触发,这时候可以给原来的位置设置元素样式等等。