elementUI + vue实现 Excel筛选功能

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>

各种数据请使用后台接口获取。

实现效果

在这里插入图片描述

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Element UI是一套基于Vue.js的组件库,而SheetJS是一个用于读写Excel文件的JavaScript库。如果想在Vue 3中使用Element UI和SheetJS来导出Excel文件,可以按照以下步骤进行: 首先,安装Element UI和SheetJS的依赖包。可以通过npm或yarn来安装这两个库。 ```bash npm install element-ui sheetjs ``` 接下来,在Vue的入口文件(main.js)中引入Element UI和SheetJS,并将其注册为全局组件。 ```javascript import { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/lib/theme-chalk/index.css' import * as XLSX from 'xlsx' import App from './App.vue' const app = createApp(App) app.use(ElementPlus) app.config.globalProperties.$xlsx = XLSX app.mount('#app') ``` 然后,在需要导出Excel的组件中,可以使用Element UI的按钮组件来触发导出操作。 ```vue <template> <div> <el-button @click="exportExcel">导出Excel</el-button> </div> </template> <script> import { ref } from 'vue' export default { methods: { exportExcel() { const worksheet = XLSX.utils.aoa_to_sheet([['Hello', 'World']]) const workbook = XLSX.utils.book_new() XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1') XLSX.writeFile(workbook, 'example.xlsx') } } } </script> ``` 在上面的示例代码中,我们在exportExcel方法中创建了一个SheetJS的工作表(worksheet),然后将其添加到工作簿(workbook)中,并将其写入一个名为"example.xlsx"的文件中。 最后,记得在组件中引入SheetJS库。 ```javascript import * as XLSX from 'xlsx' ``` 这样就完成了在Vue 3中使用Element UI和SheetJS导出Excel文件的操作。通过这种方式,我们可以方便地将数据导出为Excel文件,实现更灵活的数据处理和展示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值