Vue + Element UI el-table + sortablejs 行、列拖拽排序

实现Element UI中的el-table表格组件的行和列的拖拽排序

使用 Vue3 + Element Plus UI + sortablejs

安装sortablejs

pnpm install sortablejs

行拖拽

基本实现

效果
在这里插入图片描述

<script setup>
import { onMounted, ref } from "vue";
import Sortable from "sortablejs";

const tableData = ref([
  {
    id: 1,
    date: "2016-05-02",
    name: "王小虎111",
    age: 21,
    address: "上海市普陀区金沙江路 1518 弄",
  },
  {
    id: 2,
    date: "2016-05-04",
    name: "王小虎222",
    age: 22,
    address: "上海市普陀区金沙江路 1517 弄",
  },
  {
    id: 3,
    date: "2016-05-01",
    name: "王小虎333",
    age: 23,
    address: "上海市普陀区金沙江路 1519 弄",
  },
  {
    id: 4,
    date: "2016-05-03",
    name: "王小虎444",
    age: 24,
    address: "上海市普陀区金沙江路 1516 弄",
  },
  {
    id: 5,
    date: "2016-05-08",
    name: "王小虎555",
    age: 25,
    address: "上海市普陀区金沙江路 1518 弄",
  },
]);

onMounted(() => {
  rowDrop();
});

/**
 * 行拖拽排序
 */
function rowDrop() {
  // 要侦听拖拽响应的DOM对象
  const tbody = document.querySelector(".el-table__body-wrapper tbody");
  const data = tableData.value;
  Sortable.create(tbody, {
    // handle: ".el-icon-rank",
    ghostClass: "target-row-class",
    // 结束拖拽后的回调函数
    onEnd({ newIndex, oldIndex }) {
      // 将oldIndex位置的数据删除并取出,oldIndex后面位置的数据会依次前移一位
      const currentRow = data.splice(oldIndex, 1)[0];
      // 将被删除元素插入到新位置(currRow表示上面的被删除数据)
      data.splice(newIndex, 0, currentRow);
    },
  });
}
</script>

<template>
  <el-table
    ref="table"
    :data="tableData"
    style="width: 100%"
    border
    row-key="id"
  >
    <el-table-column prop="date" label="日期" />
    <el-table-column prop="name" label="姓名" />
    <el-table-column prop="age" label="年龄" />
    <el-table-column prop="address" label="地址" />
    <!--<el-table-column align="center" width="55">-->
    <!--  <i class="el-icon-rank" />-->
    <!--</el-table-column>-->
  </el-table>
</template>

<style scoped lang="less">
.el-table {
  ::v-deep {
    .target-row-class {
      background: #f0f9eb;
    }
  }
}
</style>

禁止某几行拖拽

效果
在这里插入图片描述

<script setup>
import { onMounted, ref } from "vue";
import Sortable from "sortablejs";

const tableData = ref([
  {
    id: 1,
    date: "2016-05-02",
    name: "王小虎111",
    age: 21,
    address: "上海市普陀区金沙江路 1518 弄",
  },
  {
    id: 2,
    date: "2016-05-04",
    name: "王小虎222",
    age: 22,
    address: "上海市普陀区金沙江路 1517 弄",
  },
  {
    id: 3,
    date: "2016-05-01",
    name: "王小虎333",
    age: 23,
    address: "上海市普陀区金沙江路 1519 弄",
  },
  {
    id: 4,
    date: "2016-05-03",
    name: "王小虎444",
    age: 24,
    address: "上海市普陀区金沙江路 1516 弄",
  },
  {
    id: 5,
    date: "2016-05-08",
    name: "王小虎555",
    age: 25,
    address: "上海市普陀区金沙江路 1518 弄",
  },
]);

onMounted(() => {
  rowDrop();
});

/**
 * 行拖拽排序
 */
function rowDrop() {
  // 要侦听拖拽响应的DOM对象
  const tbody = document.querySelector(".el-table__body-wrapper tbody");
  const data = tableData.value;
  Sortable.create(tbody, {
    // handle: ".el-icon-rank",
    ghostClass: "target-row-class",
    // 匹配的元素将不会触发拖动
    filter: ".filtered",
    // 拖拽移动事件,返回false取消移动
    onMove: function ({ related }) {
      return related.className.indexOf("filtered") === -1;
    },
    // 结束拖拽后的回调函数
    onEnd({ newIndex, oldIndex }) {
      // 将oldIndex位置的数据删除并取出,oldIndex后面位置的数据会依次前移一位
      const currentRow = data.splice(oldIndex, 1)[0];
      // 将被删除元素插入到新位置(currRow表示上面的被删除数据)
      data.splice(newIndex, 0, currentRow);
    },
  });
}

// 设置ID为1和5的行禁止拖拽
function tableRowClassName({ row, rowIndex }) {
  const freezeList = [1, 5];
  return freezeList.includes(row.id) ? "filtered" : "";
}
</script>

<template>
  <el-table
    ref="table"
    :data="tableData"
    style="width: 100%"
    border
    row-key="id"
    :row-class-name="tableRowClassName"
  >
    <el-table-column prop="date" label="日期" />
    <el-table-column prop="name" label="姓名" />
    <el-table-column prop="age" label="年龄" />
    <el-table-column prop="address" label="地址" />
    <!--<el-table-column align="center" width="55">-->
    <!--  <i class="el-icon-rank" />-->
    <!--</el-table-column>-->
  </el-table>
</template>

<style scoped lang="less">
.el-table {
  ::v-deep {
    .target-row-class {
      background: #f0f9eb;
    }
	// 禁止拖拽行背景色
    .filtered {
      background-color: #1db1e7 !important;
    }
  }
}
</style>

列拖拽

基本实现

效果
在这里插入图片描述

<script setup>
import { onMounted, ref } from "vue";
import Sortable from "sortablejs";

const columns = ref([
  { label: "日期", prop: "date" },
  { label: "姓名", prop: "name" },
  { label: "年龄", prop: "age" },
  { label: "地址", prop: "address" },
]);

const tableData = ref([
  {
    id: 1,
    date: "2016-05-02",
    name: "王小虎111",
    age: 21,
    address: "上海市普陀区金沙江路 1518 弄",
  },
  {
    id: 2,
    date: "2016-05-04",
    name: "王小虎222",
    age: 22,
    address: "上海市普陀区金沙江路 1517 弄",
  },
  {
    id: 3,
    date: "2016-05-01",
    name: "王小虎333",
    age: 23,
    address: "上海市普陀区金沙江路 1519 弄",
  },
  {
    id: 4,
    date: "2016-05-03",
    name: "王小虎444",
    age: 24,
    address: "上海市普陀区金沙江路 1516 弄",
  },
  {
    id: 5,
    date: "2016-05-08",
    name: "王小虎555",
    age: 25,
    address: "上海市普陀区金沙江路 1518 弄",
  },
]);

onMounted(() => {
  columnDrop();
});

/**
 * 列拖拽排序
 */
function columnDrop() {
  // 要侦听拖拽响应的DOM对象
  const wrapperTr = document.querySelector(".el-table__header-wrapper tr");
  Sortable.create(wrapperTr, {
    animation: 180,
    delay: 0,
    onEnd({ newIndex, oldIndex }) {
      const draggedItem = columns.value.splice(oldIndex, 1)[0];
      columns.value.splice(newIndex, 0, draggedItem);
    },
  });
}
</script>

<template>
  <el-table
    ref="table"
    :data="tableData"
    style="width: 100%"
    border
    row-key="id"
  >
    <el-table-column
      v-for="(column, index) in columns"
      :key="index"
      :prop="column.prop"
      :label="column.label"
    />
  </el-table>
</template>

禁止某几行拖拽

效果
在这里插入图片描述

<script setup>
import { onMounted, ref } from "vue";
import Sortable from "sortablejs";

const columns = ref([
  { label: "日期", prop: "date" },
  { label: "姓名", prop: "name", draggable: true },
  { label: "年龄", prop: "age", draggable: true },
  { label: "地址", prop: "address" },
]);

const columnsDrop = ref([
  { label: "日期", prop: "date" },
  { label: "姓名", prop: "name" },
  { label: "年龄", prop: "age" },
  { label: "地址", prop: "address" },
]);

const tableData = ref([
  {
    id: 1,
    date: "2016-05-02",
    name: "王小虎111",
    age: 21,
    address: "上海市普陀区金沙江路 1518 弄",
  },
  {
    id: 2,
    date: "2016-05-04",
    name: "王小虎222",
    age: 22,
    address: "上海市普陀区金沙江路 1517 弄",
  },
  {
    id: 3,
    date: "2016-05-01",
    name: "王小虎333",
    age: 23,
    address: "上海市普陀区金沙江路 1519 弄",
  },
  {
    id: 4,
    date: "2016-05-03",
    name: "王小虎444",
    age: 24,
    address: "上海市普陀区金沙江路 1516 弄",
  },
  {
    id: 5,
    date: "2016-05-08",
    name: "王小虎555",
    age: 25,
    address: "上海市普陀区金沙江路 1518 弄",
  },
]);

// 定义变量来记录固定列的class名
const fixedColumnClass = "filtered";

onMounted(() => {
  columnDrop();
});

function setHeaderCellClass({ column }) {
  const columnLabels = columns.value
    .filter((column) => column.draggable)
    .map((column) => column.label);
  return !columnLabels.includes(column.label) ? fixedColumnClass : "";
}

/**
 * 列拖拽排序
 */
function columnDrop() {
  // 要侦听拖拽响应的DOM对象
  const wrapperTr = document.querySelector(".el-table__header-wrapper tr");
  Sortable.create(wrapperTr, {
    animation: 180,
    delay: 0,
    ghostClass: "target-row-class",
    filter: `.${fixedColumnClass}`,
    // filter: (event, item) => {
    //   // 也可以根据item的类名、id或其他属性来决定是否应该被排除
    //   return !item.classList.contains("draggable");
    // },
    onMove: function ({ related }) {
      return related.className.indexOf(fixedColumnClass) === -1;
    },
    onEnd({ newIndex, oldIndex }) {
      const draggedItem = columnsDrop.value.splice(oldIndex, 1)[0];
      columnsDrop.value.splice(newIndex, 0, draggedItem);
    },
  });
}
</script>

<template>
  <el-table
    ref="table"
    :data="tableData"
    style="width: 100%"
    border
    row-key="id"
    :header-cell-class-name="setHeaderCellClass"
  >
    <el-table-column
      v-for="(column, index) in columns"
      :key="column.prop"
      :prop="columnsDrop[index].prop"
      :label="column.label"
    />
  </el-table>
</template>

<style scoped lang="less">
.el-table {
  ::v-deep {
    .target-row-class {
      background: #f0f9eb;
    }

    .filtered {
      background-color: #1db1e7 !important;
    }
  }
}
</style>

封装Vue指令

未完待续

  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
el-tableel-table-column是Element UI库中的两个组件,用于展示表格数据。自定义指令可以用于对el-tableel-table-column进扩展和定制。 对于el-table,可以使用自定义指令来实现一些特定的功能,比如自定义排序拖拽宽、固定表头等。通过自定义指令,可以在el-table上添加一些额外的为或样式。 对于el-table-column,可以使用自定义指令来实现一些特定的样式或为。比如,可以通过自定义指令来实现某一的特殊渲染、宽自适应等功能。 下面是一个示例,展示如何使用自定义指令来扩展el-tableel-table-column: 1. 创建一个自定义指令: ```javascript Vue.directive('my-directive', { bind: function (el, binding, vnode) { // 在绑定时执的逻辑 // 可以在这里修改el-tableel-table-column的为或样式 }, inserted: function (el, binding, vnode) { // 在元素插入到DOM时执的逻辑 }, update: function (el, binding, vnode, oldVnode) { // 在组件更新时执的逻辑 }, componentUpdated: function (el, binding, vnode, oldVnode) { // 在组件更新完成后执的逻辑 }, unbind: function (el, binding, vnode) { // 在解绑时执的逻辑 } }); ``` 2. 在el-tableel-table-column上使用自定义指令: ```html <el-table v-my-directive> <!-- 表格内容 --> </el-table> <el-table-column v-my-directive> <!-- 内容 --> </el-table-column> ``` 通过上述方式,你可以根据自己的需求来扩展和定制el-tableel-table-column的为和样式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值