Vue3可拖动排序和删除的列表

864 阅读1分钟

发现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 }}.&nbsp;</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元素内容。