共计 4469 个字符,预计需要花费 12 分钟才能阅读完成。
问题形容
这两天产品新加了这样的一个需要:因为 el-table 的列挺多的,就想加一个配置列的性能,就是在配置面板外面外面有很多复选框,一个复选框对应一个列的名字。勾选复选框,对应列呈现,勾销勾选,对应列暗藏。点击保留列配置,就会记住用户想要显示的列和想要暗藏的列,下次再进来页面的时候,用户看到的还是用户上次在配置面板勾选的对应的复选框和勾选中的复选框对应就是表格显示的列,未勾选的复选框就是表格要暗藏的列。
话不多说,咱们先看一下最终的效果图:
实现思路
思路就是:咱们通过 vue 的监听性能来监听复选框的变动,当复选框产生了变动的时候,咱们看对应复选框的选中和未选中的值。选中的为 true 让对应的列显示、暗藏的为 false 让对应的列暗藏。当然因为 vue 是数据的双向绑定的,所以咱们就让对应的列的暗藏和表格的暗藏一一对应即可。
html 局部图示剖析
js 局部图示剖析
总结
思路就是做配置,而后监听变动。最初是案例残缺代码
仔细的敌人发现,这里的存储是存到本地的,其实更优化的做法是让后端写一个接口,把对应的列的配置数据通过接口存到数据库,而后初始化再取出来用的。不过思路是一样的,优先举荐存数据库
案例残缺代码
<template> | |
<div id="app"> | |
<el-table :data="tableData" border style="width: 100%" ref="table"> | |
<el-table-column | |
fixed | |
prop="date" | |
label="日期" | |
width="150" | |
v-if="showColumn.date" | |
> | |
</el-table-column> | |
<el-table-column | |
prop="name" | |
label="姓名" | |
width="120" | |
v-if="showColumn.name" | |
> | |
</el-table-column> | |
<el-table-column | |
prop="province" | |
label="省份" | |
width="120" | |
v-if="showColumn.provinces" | |
> | |
</el-table-column> | |
<el-table-column | |
prop="city" | |
label="市区" | |
width="120" | |
v-if="showColumn.city" | |
> | |
</el-table-column> | |
<el-table-column | |
prop="address" | |
label="地址" | |
width="300" | |
v-if="showColumn.adreess" | |
> | |
</el-table-column> | |
<el-table-column | |
prop="zip" | |
label="邮编" | |
width="120" | |
v-if="showColumn.zipCode" | |
> | |
</el-table-column> | |
<el-table-column fixed="right" width="100" align="center"> | |
<template slot="header"> | |
<i | |
class="el-icon-setting" | |
style="font-size: 22px; cursor: pointer" | |
@click="showColumnOption" | |
></i> | |
</template> | |
<template slot-scope="scope"> | |
<el-button @click="handleClick(scope.row)" type="text" size="small" | |
> 查看 </el-button | |
> | |
<el-button type="text" size="small"> 编辑 </el-button> | |
</template> | |
</el-table-column> | |
</el-table> | |
<!-- 配置列面板 --> | |
<transition name="fade"> | |
<div class="columnOption" v-show="isShowColumn"> | |
<div class="content"> | |
<div class="head"> 抉择显示字段 </div> | |
<div class="body"> | |
<el-checkbox v-model="checkList.date" disabled> 日期 </el-checkbox> | |
<el-checkbox v-model="checkList.name"> 姓名 </el-checkbox> | |
<el-checkbox v-model="checkList.provinces"> 省份 </el-checkbox> | |
<el-checkbox v-model="checkList.city"> 市区 </el-checkbox> | |
<el-checkbox v-model="checkList.adreess"> 地址 </el-checkbox> | |
<el-checkbox v-model="checkList.zipCode"> 邮编 </el-checkbox> | |
</div> | |
<div class="footer"> | |
<el-button size="small" type="primary" plain @click="saveColumn" | |
> 保留列配置 </el-button | |
> | |
</div> | |
</div> | |
</div> | |
</transition> | |
</div> | |
</template> | |
<script> | |
export default {data() { | |
return { | |
isShowColumn: false, | |
tableData: [ | |
{ | |
date: "2016-05-02", | |
name: "王小虎", | |
province: "上海", | |
city: "普陀区", | |
address: "上海市普陀区金沙江路 1518 弄", | |
zip: 200333, | |
}, | |
{ | |
date: "2016-05-04", | |
name: "王小虎", | |
province: "上海", | |
city: "普陀区", | |
address: "上海市普陀区金沙江路 1517 弄", | |
zip: 200333, | |
}, | |
{ | |
date: "2016-05-01", | |
name: "王小虎", | |
province: "上海", | |
city: "普陀区", | |
address: "上海市普陀区金沙江路 1519 弄", | |
zip: 200333, | |
}, | |
{ | |
date: "2016-05-03", | |
name: "王小虎", | |
province: "上海", | |
city: "普陀区", | |
address: "上海市普陀区金沙江路 1516 弄", | |
zip: 200333, | |
}, | |
], | |
// 列的配置化对象,存储配置信息 | |
checkList: {}, | |
showColumn: { | |
date: true, | |
name: true, | |
provinces: true, | |
city: true, | |
adreess: true, | |
zipCode: true, | |
}, | |
}; | |
}, | |
watch: { | |
// 监听复选框配置列所有的变动 | |
checkList: {handler: function (newnew, oldold) {// console.log(newnew); | |
this.showColumn = newnew; | |
// 这里须要让表格从新绘制一下,否则会产生固定列错位的状况 | |
this.$nextTick(() => {this.$refs.table.doLayout(); | |
}); | |
}, | |
deep: true, | |
immediate: true | |
}, | |
}, | |
mounted() { | |
// 发申请失去 checkListInitData 的列的名字 | |
if(localStorage.getItem("columnSet")){this.checkList = JSON.parse(localStorage.getItem("columnSet")) | |
}else{ | |
this.checkList = { | |
date: true, | |
name: true, | |
provinces: true, | |
city: true, | |
adreess: true, | |
zipCode: true, | |
}; | |
} | |
}, | |
methods: {handleClick(row) {console.log(row); | |
}, | |
showColumnOption() {this.isShowColumn = true;}, | |
saveColumn() {localStorage.setItem("columnSet",JSON.stringify(this.checkList)) | |
this.isShowColumn = false; | |
}, | |
}, | |
}; | |
</script> | |
<style lang="less" scoped> | |
.columnOption { | |
position: fixed; | |
z-index: 20; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(0, 0, 0, 0.3); | |
display: flex; | |
flex-direction: row-reverse; | |
.content { | |
width: 100px; | |
height: 100%; | |
background-color: rgb(203, 223, 198); | |
.head { | |
width: 100%; | |
height: 44px; | |
border-bottom: 1px solid #000; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
font-size: 12px; | |
} | |
.body { | |
width: 100%; | |
height: calc(100% - 88px); | |
box-sizing: border-box; | |
padding-top: 10px; | |
overflow-y: auto; | |
.items { | |
width: 100%; | |
height: 100%; | |
overflow-y: auto; | |
display: flex; | |
flex-direction: column; | |
.el-checkbox { | |
width: 100%; | |
height: 28px; | |
line-height: 28px; | |
margin-bottom: 14px; | |
display: inline-block; | |
font-family: PingFang SC; | |
font-style: normal; | |
font-weight: normal; | |
font-size: 14px; | |
color: #000; | |
overflow: hidden; | |
text-overflow: ellipsis; | |
white-space: nowrap; | |
box-sizing: border-box; | |
padding-left: 14px; | |
} | |
.el-checkbox:hover {background-color: #f5f7fa;} | |
} | |
} | |
.footer { | |
width: 100%; | |
height: 44px; | |
border-top: 1px solid #000; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
} | |
} | |
} | |
// 管制淡入淡出成果 | |
.fade-enter-active, | |
.fade-leave-active {transition: opacity 0.3s;} | |
.fade-enter, | |
.fade-leave-to {opacity: 0;} | |
</style> |
正文完