效果预览
table可拖拽
- 安装依赖
pnpm i sortablejs
- 封装table组件
<template>
<div class="tableBox cmt-16">
<el-table
:data="tableData"
class="ELtable"
:height="height"
:width="width"
stripe
:header-cell-style="{ background: '#F3F3F4', color: '#323233' }"
:row-key="
(row) => {
return row.id;
} "
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="30" :reserve-selection="true" class-name="selected"></el-table-column>
<el-table-column label="序号" type="index" align="center" class-name="selected" width="100"></el-table-column>
<el-table-column
v-for="(column, index) in tableColumns"
:key="`col_${index}_${mykey}`"
:label="column.label"
:prop="column.prop"
:index="index"
:row-index="null"
:sortable="true"
:min-width="column.width ? column.width : 100"
class-name="allow-drag"
></el-table-column>
</el-table>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import Sortable from "sortablejs"; //http://www.sortablejs.com/options.html 配置项中文文档
// 表格数据
const props = defineProps({
tableData: {
type: [Array],
defaule: [],
},
tableColumns: {
type: [Array],
defaule: [],
},
height: {
type: [Number, String],
default: "auto",
},
width: {
type: [Number, String],
default: "100%",
},
});
const emits = defineEmits<{
(event: "changeCol", data: Object): void;
(event: "changeRow", data: Object): void;
}>();
onMounted(() => {
rowDrop();
columnDrop();
});
// 行拖拽
const rowDrop = () => {
const tbody = document.querySelector(".ELtable tbody");
Sortable.create(tbody, {
animation: 150, //动画参数
onEnd({ newIndex, oldIndex }) {
// const currRow = tableData.value.splice(oldIndex, 1)[0]
// tableData.value.splice(newIndex, 0, currRow)
// 在此触发父组件中的方法
emits("changeRow", { oldIndex: oldIndex, newIndex: newIndex });
},
});
};
// 列拖拽
const columnDrop = () => {
const tbody = document.querySelector(".ELtable tr");
Sortable.create(tbody, {
animation: 180,
delay: 10,
filter: ".selected", // 过滤器,给不需要进行拖动的元素加上此类名,该元素不能主动拖动,但是其他的可拖动的依然可以与该元素交换位置
draggable: ".allow-drag", //允许拖拽的项目类名,没有该类名的元素主动被动都不能变换
onEnd: (evt) => {
setTimeout(() => {
emits("changeCol", { oldIndex: evt.oldIndex, newIndex: evt.newIndex });
}, 500);
},
});
};
//复选框发生变化时触发
const multipleSelection = ref([]);
const handleSelectionChange = (val) => {
console.log(val, 666);
};
</script>
<style lang="scss" scoped>
</style>
- 父组件主要代码
<template>
</cusButton>
<cusTable :tableData="tableData" :tableColumns="tableColumns"
@changeCol="changeCol"
@changeRow="changeRow"
></cusTable>
</template>
<script setup lang="ts">
import { useRouter } from "vue-router";
import { ref } from "vue";
const router = useRouter();
// 表格数据
let tableData = reactive([
{
id: 1,
name: '张三',
age: 18,
},
{
id: 2,
name: '里斯',
age: 11,
},
{
id: 3,
name: '饺5子',
age: 13,
},
{
id: 4,
name: '饺子7',
age: 13,
},
{
id: 5,
name: '饺子',
age: 13,
},
{
id: 6,
name: '饺子7',
age: 13,
},
{
id: 7,
name: '饺子',
age: 13,
},
{
id: 8,
name: '饺子3',
age: 13,
},
{
id: 9,
name: '饺子7',
age: 13,
},
{
id: 10,
name: '饺子4',
age: 13,
},
{
id: 11,
name: '饺子2',
age: 13,
},
{
id: 12,
name: '饺子1',
age: 13,
},
]);
// 表格列数据
interface ColType {
label:String,
prop:String
}
let tableColumns :ColType[] = reactive([
{ label: 'id', prop: 'id' },
{ label: 'name', prop: 'name' },
{ label: 'age', prop: 'age' },
]);
// 改变列排序
const changeCol = ({oldIndex ,newIndex})=>{
const empty = 2; // 跳过选择框和序号列,根据自己场景做一个变量
const oldItem = tableColumns[oldIndex - empty]
tableColumns.splice(oldIndex-empty, 1)
tableColumns.splice(newIndex-empty, 0, oldItem)
}
// 改变行排序
const changeRow = ({oldIndex ,newIndex})=>{
const currRow = tableData.splice(oldIndex, 1)[0]
tableData.splice(newIndex, 0, currRow)
}
</script>