基于Ant-Design-Vue 封装一个可拖拽控制table 列数量的组件
前置准备:
1.安装 Ant-Design-Vue https://www.antdv.com/docs/vue/use-with-vue-cli-cn/
yarn add ant-design-vue 或者 npm install ant-design-vue
2.安装 vue-smooth-dnd vuedraggable
yarn add vuedraggable , yarn add vue-smooth-dnd
main.js
import Vue from 'vue'
import App from './App.vue'
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css'
import {
Container, Draggable } from "vue-smooth-dnd";
Vue.component('Container',Container)
Vue.component('Draggable',Draggable)
Vue.config.productionTip = false
Vue.use(Antd)
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
TableSetting.vue (基于render函数封装)
<script>
import {
Container, Draggable } from "vue-smooth-dnd"; //使用拖拽插件
export default {
data() {
return {
columns: [],
checkAll: true,
indeterminate: false,
keepColumns: [],
};
},
props: {
cloumnsTitle: {
type: Array,
default: () => [],
},
isReload: {
type: Boolean,
default: false,
},
isSize: {
type: Boolean,
default: false,
},
},
watch: {
columns: {
//监听选中 拖拽时数据变化
async handler() {
this.keepColumns = this.columns.filter((v) => {
if (v.checked) {
return v;
}
});
this.$emit("onDragAndDrop", this.keepColumns);
},
deep: true,
immediate: false,
},
},
mounted() {
this.columns = this.cloumnsTitle.map((v) => {
v.checked = true;
return v;
});
},
methods: {
//全选
onChangeAll(e) {
this.columns.forEach((v) => {
v.checked = e.target.checked;
});
Object.assign(this, {
checkAll: e.target.checked,
indeterminate: false,
});
},
//选中一列
onChangeItem(e, menu) {
menu.checked = e.target.checked;
this.keepColumns = this.columns.filter((v) => {
if (!v.checked) {
return v;
}
});
Object.assign(this, {
checkAll: this.columns.every((v) => v.checked),
indeterminate:
this.keepColumns.length == this.columns.length
? false
: this.keepColumns.length == 0
? false
: true,
});
},
//拖拽列
onDrop(e) {
//获取拖拽内容和替换内容的值
let cloumnsTitle = JSON.parse(JSON.stringify(this.columns));
let startItem = cloumnsTitle.filter((v, i) => i == e.removedIndex)[0];
let endTtem = cloumnsTitle.filter((v, i) => i == e.addedIndex)[0];
// 将拖拽内容 和 替换内容互换
cloumnsTitle[e.addedIndex] = startItem;
cloumnsTitle[e.removedIndex] = endTtem;
this.columns = cloumnsTitle;
},
//设置表格宽度
onColumnHeight(e) {
this.$emit("onChangeSize", e.key);
},
//刷新表格
onReload() {
this.$emit("onReload");
},
renderDragMenu() {
//生成拖拽列
const dropMenu = this.columns.map((menu, index) => {
return (
<Draggable>
<div class="draggable-item">
<div class="lable">
<a-icon type="more" />
<a-checkbox
checked={
menu.checked}
onClick={
(e) => this.onChangeItem(e, menu)}
>
{
menu.title}
</a-checkbox>
</div>
</div>
</Draggable>
);
});
return <Container onDrop={
(e) => this.onDrop(e)}>{
dropMenu}</Container>;
},
renderDragPane() {
const Drag = this.renderDragMenu();
return (
<div class="setting-box">
<a-tooltip v-show={
this.$props.isReload}>
<div slot="title">刷新</div>
<a-icon
onClick={
() => this.onReload()}
style={
{
cursor: "pointer" }}
type="reload"
/>
</a-tooltip>
<a-tooltip v-show={
this.$props.isSize}>
<div slot="title">密度</div>
<a-popover trigger="click">
<div slot="content">
<a-menu slot="overlay" onClick={
(e) => this.onColumnHeight(e)}>
<a-menu-item key="middle">默认</a-menu-item>
<a-menu-item key="default">中等</a-menu-item>
<a-menu-item key="small">紧凑</a-menu-item>
</a-menu>
</div>
<a-icon type="column-height" style={
{
cursor: "pointer" }} />
</a-popover>
</a-tooltip>
<a-tooltip>
<div slot="title">列设置</div>
<a-popover trigger="click">
<div slot="title">
<div class="column-handle">
<div>
<a-checkbox
v-model={
this.checkAll}
onClick={
(e) => this.onChangeAll(e)}
indeterminate={
this.indeterminate}
>
列展示
</a-checkbox>
</div>
<div></div>
</div>
</div>
<div slot="content">{
Drag}</div>
<a-icon type="setting" style={
{
cursor: "pointer" }} />
</a-popover>
</a-tooltip>
</div>
);
},
},
render() {
const dragList = this.renderDragPane();
if (this.columns.length == 0) {
return <div>请传入正确的表头参数值</div>;
}
return <div class="table-setting">{
dragList}</div>;
},
};
</script>
<style scoped>
.setting-box {
width: 60px;
margin: 0 auto;
justify-content: space-between;
display: flex;
}
.setting-box i {
font-size: 16px;
}
.table-setting >>> .ant-popover-inner-content {
padding: 0 !important;
}
.column-handle {
display: flex;
justify-content: space-between;
}
.table {
width: 70%;
margin: 0 auto;
}
.draggable-item {
padding: 4px 16px 4px 2px;
box-shadow: 1px 1px 3px #cacaca;
cursor: move !important;
}
</style>
在界面中去使用
<template>
<div class="about">
<div class="table">
<a-table
:columns="columns"
bordered
:loading="loading"
:data-source="data"
:size="size"
>
<div class="title" slot="title">
<table-setting
:cloumnsTitle="columns"
@onDragAndDrop="onDragAndDrop"
@onChangeSize="onChangeSize"
@onReload="onReload"
:isSize="true"
:isReload="true"
></table-setting>
</div>
</a-table>
</div>
</div>
</template>
<script>
import TableSetting from "@/components/TableSetting";
var data = [];
//表格数据
for (var i = 0; i < 20; i++) {
data.push({
key: i,
name: "John Brown",
age: 32,
address: "New York No. 1 Lake Park",
});
}
//表头参数
var columns = [
{
title: "name",
dataIndex: "name",
key: "name",
slots: {
title: "customTitle" },
scopedSlots: {
customRender: "name" },
},
{
title: "Age",
dataIndex: "age",
key: "age",
},
{
title: "Address",
dataIndex: "address",
key: "address",
},
{
title: "Tags",
key: "tags",
dataIndex: "tags",
scopedSlots: {
customRender: "tags" },
},
{
title: "Action",
key: "action",
scopedSlots: {
customRender: "action" },
},
];
export default {
data() {
return {
columns,
data,
size: "middle", //表格比列大小 默认 middle
loading: false,
};
},
components: {
TableSetting,
},
methods: {
//拖拽时触发
onDragAndDrop(columns) {
this.columns = columns;
},
//设置表格比列大小
onChangeSize(size) {
this.size = size;
},
//刷新表格
onReload() {
this.loading = true;
//模拟向后端请求数据
setTimeout(() => {
this.loading = false;
}, 2000);
},
},
};
</script>
<style scoped>
.table {
width: 70%;
margin: 0 auto;
}
.title{
display: flex;
justify-content: flex-end;
}
</style>
界面效果
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
@onDragAndDrop | 拖拽回调 | funtion | - |
@onChangeSize | 设置大小回调 | funtion | - |
@onReload | 刷新表格回调 | funtion | - |
isSize | 是否显示操作大小按钮 | boolean | false |
isReload | 是否显示刷新按钮 | boolean | false |
cloumnsTitle | 要操作的表头数据(必填) | Array | [] |