发现VueDraggable库的作者更新比较缓慢,似乎已经弃坑了。笔者自行使用SortableJS封装了一个类似的极简可编辑拖动的列表组件,基于Vue3 + Setup语法糖 + $ref语法糖(不太清楚的同学可以看笔者之前【自上而下】的Vue教程),使用了heroicons图标库和tailwindcss样式。
安装依赖
环境和样式就不说了,可以参考【自上而下】教程中的模板代码仓库,主要需要安装SortableJS
npm i sortablejs
封装组件EditableList
直接上代码:
<script setup>
import { onMounted } from 'vue'
import Sortable from 'sortablejs/modular/sortable.core.esm.js'
import { TrashIcon, Bars2Icon } from '@heroicons/vue/24/outline'
const props = defineProps(['list', 'itemClass'])
let el = $ref()
onMounted(() => new Sortable(el, {
handle: '.handle', animation: 150,
onUpdate: e => props.list.splice(e.newIndex, 0, props.list.splice(e.oldIndex, 1)[0])
}))
</script>
<template>
<div ref="el">
<div v-for="(e, i) in props.list" class="flex flex-wrap justify-between items-center" :class="props.itemClass" :key="e">
<slot name="item" :element="e" :index="i"></slot>
<div class="flex">
<TrashIcon class="w-4 mx-2 cursor-pointer text-red-500" @click="props.list.splice(i, 1)"/>
<Bars2Icon class="w-4 cursor-pointer handle text-gray-500" />
</div>
</div>
</div>
</template>
基本原理是使用SortableJS创建一个可以拖动的列表,根据SortableJS的事件来更新Vue中的数据。
使用组件
<EditableList :list="list" item-class="bg-white py-1 px-2 border my-2 rounded flex-nowrap">
<template #item="{ element: el, index: i }">
<div>{{ i + 1 }}. </div>
<input class="grow" v-model="list[i].title" placeholder="点击编辑选项内容">
<input type="number" v-model="list[i].space" class="border ml-2 w-12 pl-1">
</template>
</EditableList>
如上面例子所示,通过<template>标签展开一个名称为item插槽,这个插槽,可以在每行中渲染自定义的元素。
EditableList组件自带了两个图标按钮,分别对应了删除和拖拽排序。如果您有其它样式需要,可以自行修改EditableList中的v-for元素内容。