当前位置:   article > 正文

Vue + Element UI el-table + sortablejs 行、列拖拽排序_elementui plus的 el-table使用sortable拖拽,有展开行

elementui plus的 el-table使用sortable拖拽,有展开行

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

使用 Vue3 + Element Plus UI + sortablejs

安装sortablejs

pnpm install sortablejs
  • 1

行拖拽

基本实现

效果
在这里插入图片描述

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94

禁止某几行拖拽

效果
在这里插入图片描述

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

列拖拽

基本实现

效果
在这里插入图片描述

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

禁止某几行拖拽

效果
在这里插入图片描述

<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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127

封装Vue指令

未完待续

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/599549
推荐阅读