element-plus结合sortablejs实现table行拖拽效果

 更新时间:2023年10月10日 08:46:29   作者:北鸟南游  
使用element-plus的el-table组件创建出来的table,结合sortable.js实现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行拖拽的资料请关注脚本之家其它相关文章!

相关文章

  • 多个Vue项目部署到服务器的步骤记录

    多个Vue项目部署到服务器的步骤记录

    这篇文章主要给大家介绍了关于多个Vue项目部署到服务器的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Vue3 setup的注意点及watch监视属性的六种情况分析

    Vue3 setup的注意点及watch监视属性的六种情况分析

    这篇文章主要介绍了Vue3 setup的注意点及watch监视属性的六种情况,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • element el-table表格的二次封装实现(附表格高度自适应)

    element el-table表格的二次封装实现(附表格高度自适应)

    这篇文章主要介绍了element el-table表格的二次封装实现(附表格高度自适应),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • vue实现一个炫酷的日历组件

    vue实现一个炫酷的日历组件

    公司业务新开了一个商家管理微信H5移动端项目,日历控件是商家管理员查看通过日程来筛选获取某日用户的订单等数据。下面小编给大家带来了基于vue实现一个炫酷的日历组件,感兴趣的朋友参考下吧
    2018-10-10
  • Vue3中setup方法的用法详解

    Vue3中setup方法的用法详解

    在vue3版本中,引入了一个新的函数,叫做setup。这篇文章将为大家详细介绍一下Vue3中setup方法的用法,感兴趣小伙伴的可以了解一下
    2022-07-07
  • vue2如何使用vue-i18n搭建多语言切换环境

    vue2如何使用vue-i18n搭建多语言切换环境

    这篇文章主要介绍了vue2-使用vue-i18n搭建多语言切换环境的相关知识,在data(){}中获取的变量存在更新this.$i18n.locale的值时无法自动切换的问题,需要刷新页面才能切换语言,感兴趣的朋友一起看看吧
    2023-12-12
  • Vue使用Echart图标插件之柱状图

    Vue使用Echart图标插件之柱状图

    这篇文章主要为大家详细介绍了Vue使用Echart图标插件之柱状图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • Vue实现文本展开收起功能

    Vue实现文本展开收起功能

    这篇文章主要为大家详细介绍了Vue实现文本展开收起功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • Vuex Action的 { commit }的写法教程

    Vuex Action的 { commit }的写法教程

    实践中,我们会经常用到 ES2015 的参数解构来简化代码(特别是我们需要调用commit很多次的时候,{commit} 写法是解构后得到的,这篇文章主要介绍了Vuex Action的{ commit }的写法,需要的朋友可以参考下
    2023-10-10
  • Vue的elementUI实现自定义主题方法

    Vue的elementUI实现自定义主题方法

    下面小编就为大家分享一篇Vue的elementUI实现自定义主题方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02

最新评论