element-plus结合sortablejs实现table行拖拽效果
使用element-plus的el-table组件创建出来的table。结合sortable.js实现行拖动排序。
安装包 npm install -D sortablejs
使用官方table示例代码
<template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> const tableData = [ { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] </script>
引入 sortablejs 插件;
import Sortable from 'sortablejs'
然后创建排序函数实例。
const elTableRef = ref(); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, onEnd: (e) => { const targetRow = tableData.value.splice(e.oldIndex, 1) tableData.value.splice(e.newIndex, 0, targetRow[0]); }, }) }
之后可以在 onMounted
生命周期中调用下setSort。
完整的案例代码,实现基本的排序功能
<template> <el-table ref="elTableRef" :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> import Sortable from 'sortablejs' import { onMounted, ref } from 'vue'; const tableData = [ { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] const elTableRef = ref(); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, onEnd: (e) => { const targetRow = tableData.splice(e.oldIndex, 1) tableData.splice(e.newIndex, 0, targetRow[0]); }, }) } onMounted(() => { setSort(); }) </script>
数据异步加载,会出现排序混乱情况
实际业务开发中,tableData的数据都是异步获取的,接下来模拟下异步获取数据后,进行调用。
- 初始化定义tableData数据为空数组
const tableData = ref<any[]>([])
- 在setTimeout定时器中给tableData赋值。
完整代码如下:
<template> <el-table ref="elTableRef" :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> import Sortable from 'sortablejs' import { onMounted, ref } from 'vue'; const tableData = ref<any[]>([]) const elTableRef = ref(); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, onEnd: (e) => { const targetRow = tableData.value.splice(e.oldIndex, 1) tableData.value.splice(e.newIndex, 0, targetRow[0]); }, }) } onMounted(() => { setSort(); setTimeout(() => { tableData.value = [ { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] }, 200) }) </script>
?错误:此时实现出来的排序功能会有异常,如果拖动第一行到第3行下面。则会出现第1和第2行都移动到了第三行下面
之后在onEnd
钩子中查看 tableData.value
数据,会发现数据是正常的排序,1会放在3下面,2保持不动。但是页面中1和2都放在了3下。
解决办法:在el-table
中添加 row-key="date"
唯一索引属性;
取消sortable的排序
业务开发过程中,会遇到排序需要二次确认的需求。
- 如果是确认,则进行排序;
- 如果取消,则取消排序;
根据 sortablejs 官方介绍;可以在onMove、onUpdate、onEnd的回调函数中进行处理。
使用 onMove
的话,出现弹窗太早,不符合业务开发。
使用onEnd
已经完成了排序。
最后选择在onUpdate中进行二次弹窗确认。
// 列表内元素顺序更新的时候触发 onUpdate: function (/**Event*/evt) { ElMessageBox.confirm( '是否拖拽到此位置?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', } ) .then(() => { ElMessage({ type: 'success', message: '排序成功', }) return true; }) .catch(() => { ElMessage({ type: 'info', message: '取消排序', }) return false; }) },
点击取消时,代码中使用了return false;但是页面排序并没有取消掉。这时查看tableData.value的数据,排序是已经被取消。
有种似曾相识的bugger味道,在异步数据中就是数据正常,页面出现问题。使用row-key进行解决,那么现在再次出现问题是什么原因呢?
最初使用了 vue的forceUpdate
进行强制更新页面,然后并没有效果。就搜索到强制更新页面的方式,给el-table
添加一个 key 属性; :key="forceUpdate"
完整示例代码:
<template> <el-table ref="elTableRef" row-key="date" :key="forceUpdate" :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> import Sortable from 'sortablejs' import { onMounted, ref } from 'vue'; import { ElMessage, ElMessageBox } from 'element-plus' const tableData = ref<any[]>([]) const elTableRef = ref(); const forceUpdate = ref(0); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, // 列表内元素顺序更新的时候触发 onUpdate: function (/**Event*/evt) { ElMessageBox.confirm( '是否拖拽到此位置?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', } ) .then(() => { ElMessage({ type: 'success', message: '排序成功', }) return true; }) .catch(() => { ElMessage({ type: 'info', message: '取消排序', }) forceUpdate.value = Date.now(); return false; }) }, }) } onMounted(() => { setTimeout(() => { tableData.value = [ { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] }, 200) setSort(); }) </script>
?存在问题,此时只能拖动一次,点击取消排序后,整个表格的排序功能失效。
解决办法:在nextTick中重新调用下 setSort
方法;
<template> <el-table ref="elTableRef" row-key="date" :key="forceUpdate" :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> import Sortable from 'sortablejs' import { onMounted, ref, nextTick } from 'vue'; import { ElMessage, ElMessageBox } from 'element-plus' const tableData = ref<any[]>([]) const elTableRef = ref(); const forceUpdate = ref(0); const setSort = () => { const el = elTableRef?.value?.$el.querySelector('tbody') new Sortable(el, { animation: 180, delay: 0, // 列表内元素顺序更新的时候触发 onUpdate: function (/**Event*/evt) { ElMessageBox.confirm( '是否拖拽到此位置?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', } ) .then(() => { ElMessage({ type: 'success', message: '排序成功', }) return true; // 排序成功,可以调用下保存接口,将数据保存下来,然后更新下tableData数据 }) .catch(() => { ElMessage({ type: 'info', message: '取消排序', }) forceUpdate.value = Date.now(); // 重新调用下排序 nextTick(() => { setSort(); }) }) }, }) } onMounted(() => { setTimeout(() => { tableData.value = [ { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] }, 200) setSort(); }) </script>
以上就是element-plus结合sortablejs实现table行拖拽效果的详细内容,更多关于element-plus实现table行拖拽的资料请关注脚本之家其它相关文章!
相关文章
VueQuillEditor富文本上传图片(非base64)
这篇文章主要介绍了VueQuillEditor富文本上传图片(非base64),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-06-06
最新评论