表格拖拽功能

290 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第23天,点击查看活动详情

前言

今天遇到了表格拖拽功能,记录一下该功能的实现。效果如下

7.png

拖拽表格某一项时,出现不同的样式,结束拖拽后,按照最新的排序展示数据

表格拖拽实现

实现表格拖拽功能使用到了Sortable.js

安装Sortable.js

npm install sortablejs

新建article-ranking/sortable/index.js,对sortable初始化,首先看Sortable.js官网的demo,其中传入两个参数,第一个为拖拽对象,第二个为配置项

8.png

对比自己的结构

9.png

可以发现我需要获取到tbody这个节点,我们导出一个配置方法,首先需要获取到tbody节点,初始化传入的配置项中,ghostClass表示为拖拽元素添加的类名,方便后面为这个拖拽项渲染不同的样式,onEnd表示拖拽完成后执行的方法,这里暂时先不去处理里面的逻辑

还需要导出一个ref对象,和表格绑定在一起

import Sortable from 'sortablejs'
import { ref } from 'vue'

// 表格ref对象
export const tableRef = ref(null)

export const initSorttable = () => {
  // 获取到tbody节点
  const el = tableRef.value.$el.querySelectorAll(
    '.el-table__body-wrapper > table > tbody'
  )[0]
  // 拖拽元素 配置对象
  Sortable.create(el, {
    // 拖拽时类名
    ghostClass: 'sortable-ghost',
    // 拖拽结束方法
    onEnd(event) {}
  })
}
 <el-table ref="tableRef" :data="tableData" border>

接着在article-ranking.vue中导入,在onMounted中初始化

import { tableRef, initSortable } from './sortable'

// 表格拖拽相关
onMounted(() => {
  initSortable()
})

并且为拖拽项加上样式

:deep(.sortable-ghost) {
  opacity: 0.6;
  color: #fff !important;
  background: #304156 !important;
}

这样简单的拖拽效果就完成了,后面去处理拖拽完成后的逻辑

拖拽完成后

onEnd方法的event参数中可以获取到拖拽项新的下标和原来的下标,获取到后调用接口重置表格数据的排序

export const initSorttable = (tableData) => {
    ···
    onEnd(event) {
      const { newIndex, oldIndex } = event
      console.log(newIndex, oldIndex)
      // 重置排序接口
      articleSort({
        initRanking: tableData[oldIndex].value.ranking,
        finalRanking: tableData[newIndex].value.ranking
      })
    }
}

这里传入了tableData而非tableData.value,因为在挂载时数据为空,这时候传入的是空值,所以我们直接传入响应式数据,在article-ranking/sortable/index.js中通过.value的方式获取数据

const tableData = ref([])

// 初始化sortable
onMounted(() => {
  initSorttable(tableData)
})

重置排序后,希望得到排序后最新的数据

我们传入获取数据的方法getListData

// 初始化sortable
onMounted(() => {
  initSorttable(tableData, getListData)
})

接着在拖拽完成后先将tableData.value赋空,在调用方法获取数据,如果不赋空的话,表格展示的还是拖拽完成后的排序,不是获取的最新排序的数据。最后提示信息即可

export const initSorttable = (tableData, callback) => {
    ···
    onEnd(event) {
      const { newIndex, oldIndex } = event
      console.log(newIndex, oldIndex)
      articleSort({
      initRanking: tableData[oldIndex].value.ranking,
      finalRanking: tableData[newIndex].value.ranking
      })
      tableData.value = []
      callback && callback()
      ElMessage.success(i18n.global.t('msg.article.sortSuccess'))
    }
  })
}