基于vue+Element Table Popover 弹出框内置表格的封装
项目场景:
在选择数据的时候需要在已选择的数据中对比选择,具体就是点击一个按钮,弹出一个小的弹出框,但不像对话框那样还需要增加一个遮罩层,更加的轻量化,但是需要查看的数据很多需要一个列表来展示,列表的话还需要一个筛选功能。
我的思路是增加复选框列,将选择的内容插入到外部的列表中,我这里主要是分享弹出框内置列表的一个封装思路。
但是在这当中还会设计到列表、分页的方法,所以建议先搞清楚列表以及分页在来看,这些我之前的文章都有涉及。
实现效果
认识组件
老样子先根据Element的官方文档认识一下Popover 弹出框
代码
<el-popover
placement="right"
width="400"
trigger="click">
<el-table :data="gridData">
<el-table-column width="150" property="date" label="日期"></el-table-column>
<el-table-column width="100" property="name" label="姓名"></el-table-column>
<el-table-column width="300" property="address" label="地址"></el-table-column>
</el-table>
<el-button slot="reference">click 激活</el-button>
</el-popover>
<script>
export default {
data() {
return {
gridData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}]
};
}
};
</script>
效果
分析
这个是一个基础的Popover 弹出框,在这当中我们要用到的方法、函数有:
- placement:出现位置 :top/top-start/top-end/bottom/bottom-start/bottom-end/left/left-start/left-end/right/right-start/right-end
- width:弹出框宽度:800 (最小宽度 150px)
- popper-class:为 popper 添加类名:popover
- show:显示时触发:handlePopoverShow
- v-model:状态是否可见:visible
- trigger:触发方式:click/focus/hover/manual
这些就是在Popover 弹出框中要用到的内置方法及函数
封装:
代码
<!--
component:Popover弹出框(内置列表)
time:2023/08/10
placement:位置
popoverText:按钮文字
popoverIcon:按钮图表
tableType:MultipleChoice(单选)、CheckBox(多选)
tableData:列表数据
tableConfig:列表配置
loading:开启列表加载
totalNum:分页总数
width:宽度
handlePopoverShow:弹出框显示触发
handleSizeChange:分页条数
handleCurrentChange:分页页数
handleSelectData:确定触发事件
-->
<template>
<div class="popover">
<el-popover
:placement="placement"
:width="width"
popper-class="popover"
@show="handlePopoverShow"
v-model="visible"
trigger="click">
<el-form ref="PopoverQuery" label-width="80px" class="PopoverQuery">
<el-card shadow="hover">
<el-form-item :label="$t('query_condition')" class="PopoverQuery-FormItem">
<el-input class="PopoverQuery-Input" :placeholder="placeholder"></el-input>
<el-button size="mini" icon="el-icon-search">{{$t('Query')}}</el-button>
</el-form-item>
</el-card>
</el-form>
<Table ref="table" :total="totalNum" @handleSizeChange="handleSizeChange" @handleCurrentChange="handleCurrentChange" :loading="loading" :tableData="tableData" :tableConfig="tableConfig" :tableType="tableType" @RowClick="tableRowClick" @HandleSelectionChange="selectionChange"></Table>
<div class="mar-top-10" style="overflow: hidden;">
<!-- 单选清空 -->
<el-button size="mini" class="FloatRight" icon='el-icon-refresh' @click="EmptyTableSelectStatus('MultipleChoice')" v-if="tableType=='MultipleChoice'">{{ $t('empty') }}</el-button>
<!-- 多选清空 -->
<el-button size="mini" class="FloatRight" icon='el-icon-circle-close' @click="cancel('CheckBox')" v-else>{{ $t('Cancel') }}</el-button>
<el-button size="mini" type="success" class="card-title-button" @click="handleSelectData" style="margin-right:10px" icon='el-icon-circle-check'>{{ $t('determine') }}</el-button>
</div>
<el-button size="mini" class="card-title-button" :icon='popoverIcon' slot="reference">{{ popoverText }}</el-button>
</el-popover>
</div>
</template>
<script>
import Table from '@/components/table/index.vue'
export default {
components:{Table},
data() {
return {
visible:false,
selectData:[] //复选框选择的数据
};
},
props:{
popoverText:{
default(){
return [];
}
},
popoverIcon:{
default(){
return [];
}
},
tableData:{
default(){
return [];
}
},
tableConfig:{
default(){
return [];
}
},
tableType:{
default(){
return [];
}
},
loading:{
type:Boolean,
default: false
},
width:{
type:String,
default:'500',
},
totalNum:{
type:Number,
default:0
},
placement:{
type:String,
default:'bottom'
},
placeholder:{
type:String,
default:'',
}
},
methods:{
tableRowClick(row,type){ //单选列表行点击事件
console.log(type,row);
},
selectionChange(row){ //多选列表复选框点击事件
this.selectData = row
},
cancel(){
this.visible = false
},
handlePopoverShow(){ //弹出框显示触发
this.$emit('handlePopoverShow',true)
},
handleSizeChange(val) { //分页条数
this.$emit('handleSizeChange',val)
},
handleCurrentChange(val) { //分页页数
this.$emit('handleCurrentChange',val)
},
handleSelectData(){ //确认触发事件
this.$emit('handleSelectData',this.selectData)
this.visible = false
}
}
};
</script>
<style lang="scss" scoped>
.popover{
float: right;
padding-bottom: 0px;
}
.PopoverQuery{
overflow: hidden;
&-FormItem{
margin-bottom: 0px;
}
&-Input{
float: left;
width: 70%;
margin-right: 10px;
}
}
::v-deep .el-table__header-wrapper{
position: sticky;
top: -12px;
z-index: 9;
}
::v-deep .el-table__body-wrapper {
height: 310px;
overflow-y: scroll;
}
</style>
这里我们要用到的字段除了上述的还有很多,因为这个是内置了三个组件的封装组件。
封装思路
- placement:位置
- popoverText:按钮文字
- popoverIcon:按钮图表
- width:宽度
- tableType:MultipleChoice(单选)、CheckBox(多选)
- tableData:列表数据
- tableConfig:列表配置
- loading:开启列表加载
- totalNum:分页总数
- handlePopoverShow:弹出框显示触发
- handleSizeChange:分页条数
- handleCurrentChange:分页页数
- handleSelectData:确定触发事件
- 首先是将
placement,popoverText,popoverIcon,tableType,width
传给组件定义按钮的样式,类型 - 点击按钮触发
handlePopoverShow
函数,将事件传给页面,页面开始请求接口,这时会将loading
该为开启状态 - 后端回传数据后,将
loading
状态重置,在将tableData,tableConfig,totalNum
传给组件,此时列表中已经可以查看到数据了 - 最后
handleSelectData
在执行剩下的逻辑
我这里面还嵌入了一个form表单来作为数据的校验,但是还没写全,其实就是按照正常的form表单验证写就行了
页面中使用
//调用示例
<Popover
style="float: left;height: 28px;"
placement="right"
:popoverText="this.$t('add_product_details')"
popoverIcon="el-icon-thumb"
:tableData="productTableData"
:tableConfig="productTableConfig"
:tableType="'CheckBox'"
:loading="productTableloading"
:totalNum="paging.totalNum"
width="800"
@handlePopoverShow="getFirstLegOrderlog"
@handleSizeChange="handleSizeChange"
@handleCurrentChange="handleCurrentChange"
@handleSelectData="handleSelectData"
>
</Popover>