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>
<div class="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>
各种数据请使用后台接口获取。