*注:示例使用的是vue3和element+进行二次封装的
首先我们来看效果图(总共可以分为以下几个模块):
- 表格数据操作按钮区域
- 表格信息提示区域
- 表格主体内容展示区域
- 表格分页区域
表单搜索没有封装在这里是为了降低代码的耦合性(有兴趣的可以查看我之前写的搜索框封装如何封装一个后管的输入框按钮组件基础版(可多次复用)_小羊集事笨的博客-CSDN博客)
以下是代码:
<script setup>
import { computed, ref } from "vue"
const props = defineProps({
// 表格按钮个数
btnArray: {
type: Array,
default: () => []
},
// 是否显示右侧提示
showTip: {
type: Boolean,
default: false
},
// 表格数据
tableData: {
type: Array,
default: () => []
},
//数据的条数
total: {
type: Number,
default: 0
},
// 头部字段
fields: {
type: Array,
default: () => []
},
// 字典(状态值,例如:0开始,1进行中,2结束)
dict: {
type: Object,
default: () => {}
},
// 是否可选
tableSelect: {
type: Boolean,
default: false
},
// 是否显示序号
tableIndex: {
type: Boolean,
default: false
},
// 是否需要加载层
loading: {
type: Boolean,
default: false
},
page: Number,
pageSize: Number
})
const operation = ref(null)
// 动态计算操作列宽度
const winth = computed(() => {
const length = operation.value?.$el.children.length
const btnsWidth = length * 15 + length * 50
return btnsWidth
})
// 车位总数
const sum = ref(666)
//动态计算占比
const Proportion = computed(() => props.total / sum.value )
const emit = defineEmits(["btnHandle", "selectionChange", "sizeChange", "currentChange"])
// 切换条数
const sizeChange = (ev) => {
emit("sizeChange", ev)
}
// 切换页数
const currentChange = (ev) => {
emit("currentChange", ev)
}
// 获取按钮颜色
const getColor = (name) => {
if (name == "批量删除") {
return ""
}
return "primary"
}
// 点击头部按钮
const btnHandle = (name) => {
emit("btnHandle", name)
}
// 点击选择框
const selectionChange = (ev) => {
emit("selectionChange", ev)
}
// 字典,处理数字对应的映射字段
const filterDictType = (value, array, code = "value", name = "label") => {
if (!value && value !== 0) {
// 要把0摘出来,一般0都是正常的数据,所以不能只用 !value
return ""
}
const findObj = array.find((item) => item[code] === value.toString() || item[code] === +value) // 字符型数值型都得匹配
if (find) {
return findObj[name]
} else {
// 没有匹配的就原样返回
return value
}
}
</script>
<template>
<el-card>
<!-- 头部按钮 -->
<div class="table-header">
<div class="header-button">
<el-button v-for="item in btnArray" :key="item" :type="getColor(item)" @click="btnHandle(item)">{{
item
}}</el-button>
</div>
<el-alert
v-if="showTip"
:title="`本园区共计 ${sum} 个车位,月卡用户 ${total}人,车位占有率 ${Proportion}%`"
show-icon
:closable="false"
/>
</div>
<!-- 表格 -->
<el-table :data="tableData" v-loading="loading" style="width: 100%" @selection-change="selectionChange">
<el-table-column v-if="tableSelect" type="selection" width="55" />
<el-table-column v-if="tableIndex" label="序号" type="index" width="55" />
<template v-for="(item, index) in fields" :key="index">
<el-table-column
show-overflow-tooltip
:prop="item.prop"
:label="item.label"
:width="item.label.indexOf('时间') >= 0 ? 220 : ''"
min-width="140"
>
<template v-slot="{ row }">
<!-- 处理根据不同的值显示不同的内容 -->
<div v-if="item.dictType">
{{ tableData.length && filterDictType(row[item.prop], dict[item.dictType]) }}
</div>
<!-- 可点击td -->
<el-link v-else-if="item.isHandle" @click="tdHandle(row.id, item.label, row)">{{ row[item.prop] }}</el-link>
<!-- 可解析html -->
<span v-else-if="item.isHtml" v-html="row[item.prop]" />
<span v-else>{{ row[item.prop] }}</span>
</template>
</el-table-column>
</template>
<!-- 操作列 -->
<el-table-column ref="operation" :width="winth + 'px'" fixed="right" label="操作">
<template v-slot="{ row }">
<slot :row="row" />
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-row justify="end">
<el-pagination
layout="total, sizes, prev, pager, next, jumper"
:page-sizes="[10, 20, 30, 40, 50]"
:total="total"
:page-size="pageSize"
:currentPage="page"
@size-change="sizeChange"
@current-change="currentChange"
/>
</el-row>
</el-card>
</template>
<style lang="scss" scoped>
.table-header {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
.el-alert--info.is-light {
height: 40px;
font-size: 14px;
border: 1px solid #91d5ff;
background-color: #e6f7ff;
:deep(.el-alert__title) {
color: #000000d9;
}
}
}
.el-alert {
width: auto;
}
.el-pagination {
margin: 16px 0;
}
:deep(.el-card__body) {
padding-bottom: 0;
}
.el-card.is-always-shadow {
box-shadow: none;
border: none;
}
</style>
这段代码是一个Vue组件,它定义了一个可重用的表格组件,具有以下功能:
-
在
<script setup>
标签中,使用Vue 3的defineProps
和defineEmits
函数定义了组件的属性(props)和事件(emits)。btnArray
:表格按钮的数组,默认为空数组。showTip
:是否显示右侧提示,默认为false。tableData
:表格数据的数组,默认为空数组。total
:数据的条数,默认为0。fields
:头部字段的数组,默认为空数组。dict
:字典,用于处理数字对应的映射字段,默认为空对象。tableSelect
:是否可选,布尔值,默认为false。tableIndex
:是否显示序号,布尔值,默认为false。loading
:是否需要加载层,布尔值,默认为false。page
:当前页数,数字类型。pageSize
:每页显示的条数,数字类型。
-
使用
ref
函数创建了operation
和sum
的引用,以及计算属性winth
和Proportion
。operation
:操作列的引用。sum
:车位总数,默认为666。winth
:动态计算操作列的宽度。Proportion
:动态计算数据条数占总数的比例。
-
使用
defineEmits
函数定义了四个事件:btnHandle
、selectionChange
、sizeChange
和currentChange
。 -
定义了一些辅助函数:
sizeChange
:切换条数的函数,当条数发生变化时触发sizeChange
事件。currentChange
:切换页数的函数,当页数发生变化时触发currentChange
事件。getColor
:根据按钮名称返回按钮颜色的函数。btnHandle
:点击头部按钮的函数,当按钮被点击时触发btnHandle
事件。selectionChange
:点击选择框的函数,当选择框的状态发生变化时触发selectionChange
事件。filterDictType
:根据字典处理数字对应的映射字段的函数。
-
在
<template>
标签中,使用Element UI的组件构建了一个表格和分页器的布局。<el-card>
:卡片容器。<div class="table-header">
:表格头部,包含按钮和提示信息。<el-button>
:头部按钮,根据btnArray
中的按钮数组动态生成。<el-alert>
:右侧提示信息,显示车位总数、总人数和占有率。<el-table>
:表格组件,用于显示表格数据。<el-table-column>
:表格列组件,根据fields
数组动态生成表格列。<el-link>
:可点击的表格单元格。<span>
:普通的表格单元格。<slot>
:插槽内容,用于显示操作列的自定义按钮或组件。<el-pagination>
:分页器组件,根据数据条数、当前页数和每页条数进行分页。
这个表格组件可以根据传入的属性和事件进行配置,生成一个带有按钮、提示信息、可选、序号、加载层、分页等功能的表格,并支持自定义操作列的按钮或组件。