封装el-table
- 目前在编写项目中,每个页面都有el-table,所以对el-table做了二次封装, 组件在个人开发使用不错,但不确定能满足各种业务需求,所以这里主要和大家分享一下设计思路。用一次爽一次,越用越爽。
分析问题:
- el-table是element-ui库的表单组件,如果我们要将其进行二次封装,那么需要考虑几个问题:
- 动态表头
- 嵌套表头
- 表格显示内容类型自定义(文字,图片,超链接等)
- 表格和分页联动
- 表格事件的处理
- 等等.
动态表头实现。
正常情况下,我们使用table:
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
prop="date"
label="日期"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
那由此我们可以设计出封装后样子:
<el-table-column
v-for="(item,index) in fieldList"
:key="index"
:prop="item.prop"
:label="item.label"
:width="item.width"
>
</el-table-column>
- 更多实现:表格显示内容、自定义、事件等等(请看↓↓组件内部)。
- 组件使用方法:( 请查看《table表格API》)。
- 依赖分页组件,要使用分页功能必须要有分页组件(请查看《page分页分装》)。
组件内部template:
<template>
<div class="Table">
<el-table
:data="data"
:max-height="maxHeight"
:row-class-name="rouClassNameFn"
:stripe="stripe"
border
@selection-change="SelectionChange"
style="width: 100%">
<!--是否显示序号-->
<el-table-column
v-if="isIndex"
label="序号"
fixed
width="50">
<!--自定义序号-->
<template v-slot="scope">
<!--索引 + 1 + (当前页数 - 1) * 每页条数-->
<span>{{scope.$index + 1 + (ispage.currentPage - 1) * ispage.pageSize }}</span>
</template>
</el-table-column>
<!--是否显示多选框-->
<el-table-column
v-if="ischeckBox"
type="selection"
fixed
width="50">
</el-table-column>
<!--是否显示单选框-->
<el-table-column
v-if="isRadio"
fixed
label="选择"
width="50">
<template scope="scope">
<div @click="radioChange($event,scope.row)">
<el-radio :label="scope.$index" v-model="radio">{{""}}</el-radio>
</div>
</template>
</el-table-column>
<!--渲染列表-->
<el-table-column
v-for="(item,index) in fieldList"
:prop="item.prop"
:label="item.label"
:align="item.align"
:key="index"
:fixed="item.fixed"
:min-width="item.minWidth"
:show-overflow-tooltip="showTooltip"
:formatter="item.formatter"
>
<template v-slot="scope" v-if="!item.formatter">
<!-- solt 自定义列(具名插槽) v-solt 简写 # -->
<template v-if="item.type === 'slot'">
<slot
:name="'col-' + item.prop"
:row="scope.row"
/>
</template>
<!-- 标签 -->
<el-tag v-else-if="item.type === 'tag'"
v-for="(childitem,idx) in scope.row[item.prop]"
:key="idx"
style="margin-right: 10px;"
>
{{childitem}}
</el-tag>
<!-- 图片 -->
<img
v-else-if="item.type === 'img'"
height="50px"
:src="scope.row[item.prop]"
>
<!-- 超链接 -->
<el-link v-else-if="item.type === 'href'"
:href="hrefValue?scope.row[item.prop][hrefValue.url]:scope.row[item.prop]"
:underline="false"
target="_blank">
{{hrefValue?scope.row[item.prop][hrefValue.name]:scope.row[item.prop]}}
</el-link>
<!-- 路由跳转 -->
<el-link type="primary"
v-else-if="item.type === 'router'"
@click="routerClickFn(scope.row)"
:underline="false"
>
{{scope.row[item.prop]}}
</el-link>
<!-- 其他 -->
<span v-else class="text">
{{scope.row[item.prop]}}
</span>
</template>
</el-table-column>
<!-- 操作 -->
<el-table-column
v-if="handle"
:fixed="handle.fixed"
align="center"
:label="handle.label"
:width="handle.width"
><template v-slot="scope">
<template>
<!-- 自定义操作类型 -->
<!-- <slot-->
<!-- v-if="handle.slot"-->
<!-- :name="'bt'"-->
<!-- :row="scope.row"-->
<!-- />-->
<!-- 操作按钮 -->
<el-button
v-for="(item,idx) in handle.btList"
v-if="!handle.slot"
:key="idx"
size="mini"
:type="item.type"
:icon="item.icon"
@click="handleClick(item.label, scope.row)"
>
{{ item.label }}
</el-button>
</template>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<div class="page" v-if="ispage">
<wb-page :data="params"
@currentChange="currentChangeFn"
@sizeChange="sizeChangeFn"
></wb-page>
</div>
</div>
</template>
<script>
export default {
name: 'Table',
props:{
// 渲染的表格数据
data: {
type: Array,
default: () => {
return []
}
},
// 表格的最大高度
maxHeight: {
type: String,
},
// 是否添加斑马线
stripe: {
type: Boolean,
default: true
},
// 是否显示序号
isIndex: {
type: Boolean,
default: false
},
// 是否有选择框
ischeckBox: {
type: Boolean,
default: false
},
// 是否有单选框
isRadio: {
type: Boolean,
default: false
},
// 是否超出隐藏,移入显示全部内容
showTooltip: {
type: Boolean,
default: true
},
// 表格字段配置
fieldList: {
type: Array,
default: () => {
return []
}
},
// 操作栏配置
handle: {
type: Object
},
// 是否显示分页分页参数
ispage: {
type: Object,
},
// 超链接如果是对象自定义 字段名value
hrefValue: {
type: Object,
}
},
data () {
return {
// 单选框索引
radio: 0,
// 分页参数
params: {
background:this.ispage.background,
hideOnSinglePage:this.ispage.hideOnSinglePage,
pageSize:this.ispage.pageSize,
pageSizes:this.ispage.pageSizes,
total:this.ispage.total,
currentPage:this.ispage.currentPage,
layout:this.ispage.layout,
}
}
},
methods:{
// 拿到索引
rouClassNameFn ({row,rowIndex}){
row.index = rowIndex;
this.$emit('rouClassNameEvent',row)
},
// 多选触发事件
SelectionChange (val) {
this.$emit('SelectionChange',val)
},
// 单选触发事件
radioChange (e,val) {
if (e.target.tagName === 'INPUT') return;
this.$emit('radioChange',val)
},
// 点击操作触发事件
handleClick (eventName,row){
let val = {
eventName:eventName,
row:row,val
};
this.$emit('handleClick',val)
},
// 页数改变时候触发
currentChangeFn (val) {
this.ispage.currentPage = val; // 当前页
this.$emit('currentChange',val)
},
// 选择每页显示多少条的时候触发(设置选择器后,才生效)
sizeChangeFn (val){
this.ispage.pageSize = val // 每页显示多少条
this.$emit('sizeChange',val)
},
// 点击路由跳转
routerClickFn (row) {
// console.log(row)
this.$emit('routerClick',row)
}
}
}
</script>
<style scoped>
.page{
margin-top: 50px;
}
</style>