最近在使用Laravel + Vue开发一个小项目时,需要用到拖拽排序功能,于是就用了vue.draggable.next这个组件,在使用的过程中遇到了一些小问题,在此记录一下。
版本问题
一开始没有注意,安装的是Vue.Draggable,使用的时候一直报错,搞得我云里雾里的,后来去GitHub上看了一下README才发现,Vue.Draggable适配的是Vue2.0,Vue3要使用vue.draggable.next。
正确使用组件的注意点
官方示例
<draggable v-model="myArray" tag="transition-group" item-key="id">
<template #item="{element}">
<div> {{element.name}} </div>
</template>
</draggable>
注意点:
- 不需要v-for循环,v-model填入数组后,会自动循环。
- item-key要添加,不然控制台会发出警告。
- tag要正确使用,表示要把组件渲染成的HTML Node,默认为div。
- 要使用
<template>
,#item
必填,值一定是element不可修改。
错误示范:
- 使用了v-for。
<draggable v-model="categories" tag="tbody" item-key="id" @end="onEnd">
<template #item="{element}">
<tr v-for="category in categories">
<td>{{ category.sort }}</td>
<td>{{ category.name }}</td>
</tr>
</template>
</draggable>
数据被重复循环
- 未填写item-key。
- 未正确使用tag样式会混乱,组件默认会渲染成div,但是子节点是tr,父标签为tbody才能正确显示,所以此处要添加
tag="tbody"
。
<draggable v-model="categories" item-key="id" @end="onEnd">
<template #item="{element, index}">
<tr>
<td>{{ index + 1 }}</td>
<td>{{ element.name }}</td>
</tr>
</template>
</draggable>
数据挤在一个单元格中
- 将
<template>
中的element改为其它,页面直接报错。
<draggable v-model="categories" tag="tbody" item-key="id" @end="onEnd">
<template #item="{item}">
<tr>
<td>{{ item.sort }}</td>
<td>{{ item.name }}</td>
</tr>
</template>
</draggable>
item未正确拿到数组中的对象
无法排序的问题
问题如下,条目可以拖拽,但是释放的瞬间就恢复原位了。
代码如下
const categories = usePage().props.value.categories
usePage()
是Inertiajs的用法,作用是接收从后端传递过来的数据,并响应式代理,与Vue的reactive一致。
<draggable v-model="categories" tag="tbody" item-key="id" @end="onEnd">
<template #item="{element, index}">
<tr>
<td>{{ element.sort }}</td>
<td>{{ element.name }}</td>
<td>
<n-image width="40" height="40" :src="element.icon" v-if="element.icon"/>
</td>
<td>{{ element.slug }}</td>
<td>{{ element.created_at }}</td>
<td>
<n-space>
<n-button size="small" type="primary" ghost @click="edit(element)">编辑</n-button>
<n-button size="small" type="error" ghost @click="destroy(element)">删除</n-button>
</n-space>
</td>
</tr>
</template>
</draggable>
模板部分的代码没有任何问题,其实问题就出在了usePage().props.value.categories
上,将其换成reactive后,依然无法正确排序,换成ref之后就可以了。
修改后的代码
const categories = ref(usePage().props.value.categories)