element仿照EXCEL
和后端交互数据联动筛选
公司要el-table基础上实现一个excel的功能,element的不能满足我的需求于是自己写了一个。
<>tableTool.vue组件实现
组件介绍:组件为筛选框,配合element中el-table使用 使用示例: <i class="el-icon-caret-bottom"
@click="filterData($event,'date')"></i> <tableTool v-if="showFilterTool"
ref="tableTool" :seachData="seachData" @saveSeach="saveSeach"
:allOptionsObj="allOptionsObj" :seachType="seachType"
:filterToolLeft="filterToolLeft" :filterToolTop="filterToolTop"
@closeTool="closeTool" />
在父组件中请使用showFilterTool来控制tableTool,父组件给一个控件添加点击事件,拿到点击事件的位置及需要处理的数据是属于哪一个方法如下:
filterData(e,type){ this.showFilterTool = false //点击区域控件触发时可以关闭当前的筛选框
this.$nextTick(()=>{ this.seachType = type this.filterToolTop = e.pageY
//拿到小工具的位置 this.filterToolLeft = e.pageX //拿到小工具的位置 this.showFilterTool = true
}) }, seachData:查询结果数据,可以让父级传过来进行回填注意数据结构应该为{ key:[],key1:[],....} seachData:{
name:[], address:[], date:[], }
allOptionsObj:所有的可查询条件,数据结构和seachData一样,并且key值一样 allOptionsObj:{
name:['王小虎','小明','小红','小兰'], address:['北京','上海','广州','深圳','长沙'],
date:['2016','2017','2018','2019'], }, seachType:需要查询的key(seachData的key中的一个)
seachType:'name' //默认 filterToolTop、filterToolLeft:拿到点击控件的位置得到的传入数值即可
filterToolTop:0, filterToolLeft:0, saveSeach:点击确认向父组件发送的事件,用于将筛选的结果传给父级
saveSeach(data){ console.log(data); this.seachData = data this.closeTool() },
closeTool:点击取消向父级发送的事件。 closeTool(){ this.showFilterTool = false }, <template> <
divclass="tableTool" :style="{top:filterToolTop + 10 +'px',left:filterToolLeft
+'px'}"> <el-input v-model="keyword" prefix-icon="el-input__icon el-icon-search"
type="text" placeholder="搜索" @input="seachKey" oninput=
"if(value.length>11)value=value.slice(0,100)"> </el-input> <div class=
"select-box"> <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll"
@change="handleCheckAllChange" id="checkAll">全选</el-checkbox> <el-checkbox-
group v-model="checkedList" @change="handleCheckedCitiesChange"> <el-checkbox v-
for="(item,index) in options" :label="item" :key="index"> </el-checkbox> </el-
checkbox-group> </div> <div class="bottom"> <el-button size="mini" @click=
"$emit('closeTool')">取消</el-button> <el-button type="primary" size="mini" @click
="save">确认</el-button> </div> <i class="el-icon-caret-top"></i> </div> </
template> <script> export default { name:'tableCol', props:{ filterToolLeft:{
required:true, type:Number }, filterToolTop:{ required:true, type:Number }, //
已经选中的数据 seachData:{ required:true, type:Object }, // 正在更改哪个 seachType:{ required
:true, type:String }, // 需要后端给的所有数据 allOptionsObj:{ required:true, type:Object }
, useTableToolComponent:{ default:null } }, data() { return { keyword:'',
checkAll: false, checkedList: [], options: [], isIndeterminate: true, allOptions
:[] }; }, methods: { handleCheckAllChange(val) { this.checkedList = val ? this.
allOptions: []; this.isIndeterminate = false; }, handleCheckedCitiesChange(value
) { let checkedCount = value.length; this.checkAll = checkedCount === this.
options.length; this.isIndeterminate = checkedCount > 0 && checkedCount < this.
options.length; }, save(){ this.seachData[this.seachType] = this.checkedList //
把查询条件给父组件 this.$emit('saveSeach',this.seachData) }, seachKey(){ this.allOptions
= this.allOptionsObj[this.seachType].filter(item=>item.indexOf(this.keyword)!= -
1) this.options = this.allOptions this.checkedList = [] this.checkAll = false },
setposition(){ let boxEl = document.querySelector('.tableTool') let icon =
document.querySelector('.tableTool .el-icon-caret-top') if(this.filterToolLeft +
boxEl.offsetWidth + 48 > document.body.clientWidth){ boxEl.style.transform =
'translateX(-90%)'; icon.style.left = '90%' } }, }, created(){ }, async mounted(
){ this.allOptions = this.allOptionsObj[this.seachType] this.options = this.
allOptions document.querySelector('#checkAll').click() this.setposition() },
beforeMount(){ let that = this this._close = e=>{ let isFlag = that.$el.contains
(e.target) || e.target.className.indexOf('el-icon-caret-bottom') != -1 if(!
isFlag){ that.$emit('closeTool') } } document.body.addEventListener('click',this
._close) }, beforeDestroy(){ document.body.removeEventListener('click',this.
_close) }, }; </script> <style lang="scss" scoped> .tableTool{ position: fixed;
background: #fff; box-shadow:0 0 5px #ccc; padding: 10px; z-index: 999; /deep/.
el-input__inner{ padding-left: 30px; } .select-box{ border: #ccc solid 1px;
padding: 10px; margin-top: 10px; max-height: 280px; overflow: auto; max-width:
400px; } /deep/ .el-checkbox{ display: block; margin-top: 5px; } .bottom{
display: flex; justify-content: flex-end; margin-top: 10px; } .el-icon-caret-top
{ position: absolute; color: #fff; top: -10px; } } </style>
<>使用组件
<template> <div> <el-table :data="tableList" max-height="500" border > <el-
table-column prop="name" label="姓名"> <template v-slot:header> <div> <span class=
"table-heard-filter">姓名</span> <i class="el-icon-caret-bottom" @click=
"filterData($event,'name')"></i> </div> </template> </el-table-column> <el-table
-column prop="address" label="地址" > <template v-slot:header> <div> <span class=
"table-heard-filter">地址</span> <i class="el-icon-caret-bottom" @click=
"filterData($event,'address')"></i> </div> </template> </el-table-column> <el-
table-column prop="date" label="时间"> <template v-slot:header> <div> <span class=
"table-heard-filter">时间</span> <i class="el-icon-caret-bottom" @click=
"filterData($event,'date')"></i> </div> </template> </el-table-column> </el-
table> <tableTool v-if="showFilterTool" :seachData="seachData" @saveSeach=
"saveSeach" :allOptionsObj="allOptionsObj" :seachType="seachType" :
filterToolLeft="filterToolLeft" :filterToolTop="filterToolTop" @closeTool=
"closeTool" /> </div> </template> <script> import tableTool from
'./tableTool.vue' export default { name:'test', components:{ tableTool }, data()
{ return{ seachData:{ name:[], address:[], date:[], }, seachType:'',
allOptionsObj:{ name:['王小虎','小明','小红','小兰'], address:['北京','上海','广州','深圳','长沙'],
date:['2016','2017','2017','2019'], }, positionTypeList:[], tableList:[], //
分页数据 editType:'', showFilterTool:false, filterToolTop:0, filterToolLeft:0, } },
methods:{ filterData(e,type){ this.showFilterTool = false this.$nextTick(()=>{
this.seachType = type this.filterToolTop = e.pageY this.filterToolLeft = e.pageX
this.showFilterTool = true }) }, closeTool(){ this.showFilterTool = false },
saveSeach(data){ console.log(data); this.seachData = data this.closeTool() },
close(){ this.showAdd = false }, saveBatch(data){ // 查询条件 console.log(data); },
getList(){ this.tableList = [{ date: '2019', name: '王小虎', address: '上海' }, {
date: '2016', name: '小明', address: '北京' }, { date: '2017', name: '小红', address:
'长沙' }, { date: '2018', name: '小兰', address: '深圳' },{ date: '2018', name: '小兰',
address: '长沙' }] } }, created(){ this.getList() } } </script> <style lang="less"
scoped> .table-heard-filter{ margin-right: 10px !important; } .fitlter-btn{
border: #000 solid 1px; padding: 1px; background: #1890FF; color: #fff; border-
radius: 5px; } </style>
各种数据请使用后台接口获取。
<>实现效果