最近做项目的时候需要对页面的table进行列配置的需求
子组件
<div>
<a-modal
title="列配置"
:visible="visible"
:closable="false" :footer="null"
width="800px" height="448px"
>
<div>
<a-row>
<a-col :span="18" style="padding: 0 10px 0 0;">
<a-table style="height: 400px"
:columns="columns" ref="alarmTable"
:customRow="customRow"
:data-source="tabkeData" :pagination="false">
<span slot="showOrhide" slot-scope="text, record">
<img src="@/assets/column/Vector-1.png" alt="" v-if="record.isHide" style="width:15px">
<img src="@/assets/column/Vector.png" alt="" v-else style="width:15px">
</span>
</a-table>
</a-col>
<a-col :span="6">
<div class="btns" @click="upColumn"><img src="@/assets/column/Group.png" alt="" class="icon">上移</div>
<div class="btns" @click="downColumn"><img src="@/assets/column/Group-1.png" alt="" class="icon">下移</div>
<div class="btns" @click="showOrhide"><img src="@/assets/column/Group-2.png" alt="" class="icon">显示/隐藏</div>
<div class="btns" @click="showWidth"><img src="@/assets/column/Vector-2.png" alt="" class="icon">修改列宽</div>
<div class="btns" @click="showTitle"><img src="@/assets/column/Vector-2.png" alt="" class="icon">修改标题</div>
<div class="btns" @click="coverData"><img src="@/assets/column/Vector-3.png" alt="" class="icon">还原默认值</div>
<div class="btns" @click="saveColumn" style="margin-top: 50px;"><img src="@/assets/column/Vector-4.png" alt="" class="icon">保存</div>
<div class="btns" @click="handleCancel"><img src="@/assets/column/Vector-5.png" alt="" class="icon">关闭</div>
</a-col>
</a-row>
</div>
</a-modal>
<a-modal v-model="widthModel" title="设置列宽" @ok="saveWidth">
<div>
<a-input
type="number"
onmousewheel="return false"
placeholder="请输入列宽"
style="width: 200px;"
onkeypress="return(/[\d\.]/.test(String.fromCharCode(event.keyCode)))"
v-model="wData"/>
</div>
</a-modal>
<a-modal v-model="titleModel" title="设置标题" @ok="saveTitle">
<div>
<a-input placeholder="请输入标题" style="width: 200px;" v-model="tData"/>
</div>
</a-modal>
</div>
<script>
const columns = [
{
title:'序号',
dataIndex: 'seq',
key:'seq'
},
{
title: 'ID',
dataIndex: 'dataIndex',
key: 'dataIndex',
},
{
title: '标题',
dataIndex: 'title',
key: 'title',
},
{
title: '列宽',
dataIndex: 'width',
key: 'width',
},
{
title: '显示',
key: 'isHide',
scopedSlots: { customRender: 'showOrhide' },
},
]
export default{
props:{
configShow:{
type:Boolean,
default:true
},
data:{
type:Array,
default:true
},
menuId:{
type:String,
default:true
},
columnsLocal:{
type:Array,
default:true
}
},
data(){
return{
visible:false,
selectedRowKeys:[],
tabkeData:[],
columns,
c_index:'',
widthModel:false,
wData:'',
titleModel:false,
tData:'',
default:[]//默认table
}
},
created(){
this.columnQuery();
},
// 挂载后
activated() {
// console.log('jinlai');
// this.columnQuery();
},
watch:{
configShow(val){
this.visible = val
},
data(val){
// this.tableData = val;
}
},
methods:{
showWidth(){
this.wData = this.tabkeData[this.c_index].width;
this.widthModel = true
},
saveWidth(){
//判断是否位0
if(this.wData == 0){
this.$message.error('不能为0!')
return
}
if(this.wData < 50){
this.$message.error('不能小于50!')
return
}
if(this.wData == ''){
this.$message.error('不能为空!')
return
}
this.$set(this.tabkeData[this.c_index],'width',parseInt(this.wData));
this.widthModel = false;
},
showTitle(){
this.tData = this.tabkeData[this.c_index].title;
this.titleModel = true;
},
saveTitle(){
if(this.tData == ''){
this.$message.error('标题不能为空!')
return
}
this.$set(this.tabkeData[this.c_index],'title',this.tData);
this.titleModel = false;
},
customRow(record, index){
return {
style: {
'background-color': this.c_index=== index ? '#Bae2d8' : ''
},
on: {
click: event => {
this.c_index = index
}
}
}
},
handleCancel(){
this.$emit('configCancle',false)
},
coverData(){
this.tabkeData = this.resetData(this.columnsLocal);
window.location.href = window.location.href
},
isLastIndex(){
return this.c_index === this.tabkeData.length - 1 || this.c_index === 0;
},
isFirstIndex(){
return this.c_index === 0 || this.c_index === 1
},
upColumn(){
let tag = this.isFirstIndex();
if(tag){
this.$message.error('不能再操作啦!')
}else{
let index = this.c_index;
let editColumn = this.tabkeData;
let t = editColumn[index];
editColumn[index] = editColumn[index-1];
editColumn[index-1] = t;
editColumn[index].seq = index+1;
editColumn[index-1].seq = index;
this.c_index = index-1;
this.$delete(this.tabkeData, 'editColumn')
this.$set(this.tabkeData,'editColumn',editColumn);
}
},
downColumn(){
let tag = this.isLastIndex();
if(tag){
this.$message.error('不能再操作啦!')
}else{
let index = this.c_index;
let editColumn = this.tabkeData;
let t = editColumn[index];
editColumn[index] = editColumn[index+1];
editColumn[index+1] = t;
editColumn[index].seq = index+1;
editColumn[index+1].seq = index+2;
this.c_index = index+1;
this.$delete(this.tabkeData, 'editColumn')
this.$set(this.tabkeData,'editColumn',editColumn);
}
},
showOrhide(){
let idx = this.c_index;
let hide = this.tabkeData[this.c_index].isHide
if(idx<=1&&hide==false){
this.$message.error('无法隐藏!')
return
}
this.tabkeData[idx].isHide = !hide;
},
async saveColumn(){
let col = this.tabkeData;
col.map((item,index) => {
if(item.scopedSlots){item.scopedSlots = JSON.stringify(item.scopedSlots)}
})
let res = await this.axios.post(
'base/v1/masterData/tableColumn/save',
{
userId: this.$store.state.user.id,
menuId: this.menuId,
columns:col
}
)
if(res.data.code == 1){
this.$message.success('保存成功!');
this.tabkeData.map(k=>{
if(k.scopedSlots){
k.scopedSlots = JSON.parse(k.scopedSlots)
}else{
delete k.scopedSlots
}
})
this.$emit('configCancle',false);
this.$emit('cover',[]);
window.location.href = window.location.href
this.$emit('cover', this.tabkeData.filter(i=>{return i.isHide==false}));
}else{
this.$message.error(res.data.messageDetail)
}
},
async columnQuery(){
//获取当前菜单的列配置 如果没有 那么默认取当前页面的 如果有那么覆盖
this.axios.post(
'xxxxxx'/xxxxxxx/xxxxxx',
{
"userId": this.$store.state.user.id,
"menuId": this.menuId
}
).then(res => {
if(res.data.code == 1){
if(res.data.result.length>0){
res.data.result.map((item,index) => {
//覆盖本地列配置
item.key = item.dataIndex
if(item.scopedSlots){
item.scopedSlots = JSON.parse(item.scopedSlots)
console.log(item.scopedSlots,'scopedSlots');
}else{
delete item.scopedSlots
}
})
this.tabkeData = res.data.result;
console.log( res.data.result,'result');
this.$emit('cover', res.data.result.filter(i=>{return i.isHide==false}));
}else{
//没有查询到数据那么判定当前没有配置过 所以第一次是取本地的数据
//this.tableData = this.data
console.log(this.columnsLocal,'this.columnsLocal---')
let c_ary = this.resetData(this.columnsLocal);
this.tabkeData = c_ary;
this.$emit('cover', this.tabkeData.filter(i=>{return i.isHide==false}));
//在本地保存一套默认的table
// this.default = c_ary
}
}
})
},
resetData(e){
let newAry = []
e.map((item,index) => {
let obj = {
align:item.align||'',
authority:item.authority||'',
dataIndex:item.dataIndex||item.key,
title:item.title,
ellipsis:true,
isFixed:false,
is_Default:true,
isHide:false,
seq:index+1,
width:item.width,
remark:item.remark||'',
key:item.key||item.dataIndex
}
if(item.scopedSlots){
obj.scopedSlots = {"customRender":obj.dataIndex}
}
newAry.push(obj)
})
return newAry;
}
}
}
</script>
子组件的有一部分代码应该是不必要的 遇到的难题是在于子组件数据更新了之后父组件数据更新了但是拖拽的功能没办法同时更新渲染 最后发现如果需要同时更新视图的话 是需要用到this.$set这个办法的 set方法没办法整个数组都更新 所以最后循环遍历更新 不知道有没有更好的办法 如果有 可以留言告诉我 谢谢~
父组件引用
<columnConfig
:configShow="configShow"
:data="columns" :columnsLocal="columnsLocal"
:menuId="menuId"
@configCancle="(e)=>{configShow=e}"
@cover="coverData">
</columnConfig>
configShow 定义弹框隐藏显示 columns传给子组件table的列配置数据 columnsLocal本地的列配置数据 初始化的时候会查询这个菜单是否有进行列配置过 如果没有那么就取本地的列配置 menuId 菜单id
customRow 这个方法也可以操作列配置显示隐藏 但是会有一个问题 确实是把head隐藏了 但是隐藏了之后原有的head还是会占位子 没有那么灵活 所以不建议用这个办法