【ElementPlus】在Vue3中实现表格组件封装
预览
搜索筛选组件
<template>
<div>
<el-form
ref="formView"
:model="formData"
label-width="auto"
label-position="right"
:label-col-style="{ 'min-width': '100px' }"
:inline="true"
>
<el-form-item :prop="column.prop" :label="column.label" v-for="column in columns" :key="column.prop">
<slot :name="column.prop" :query="formData">
<el-input v-model="formData[column.prop]" :placeholder="`请输入${column.label}`" clearable />
</slot>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="onSubmit">查询</el-button>
<el-button icon="Refresh" @click="onReset">重置</el-button>
</el-form-item>
<div class="mb15">
<slot name="handleMenu" />
</div>
</el-form>
</div>
</template>
<script setup>
import { ref, toRaw, watch, onMounted } from "vue"
const props = defineProps(["columns"])
const emit = defineEmits(["change", "submit", "reset"])
const formView = ref(null)
let formData = ref()
let isReset = false
watch(
() => formData,
(data) => {
if (isReset) {
isReset = false
return
}
emit("change", toRaw(data.value))
},
{ deep: true, immediate: true }
)
onMounted(() => {
formData.value = columnsToFormData()
})
function onSubmit() {
emit("submit", toRaw(formData.value))
}
function onReset() {
isReset = true
formData.value = columnsToFormData()
emit("reset", toRaw(formData.value))
}
function columnsToFormData() {
return Object.fromEntries(
[].concat(
...props.columns.map((item) => {
if (item.items) {
return item.items.map((iItem) => [iItem.prop, item?.defaultValue || null])
}
return [[item.prop, item?.defaultValue || null]]
})
)
)
}
</script>
表格组件
<template>
<div>
<!-- 筛选条件相关 -->
<query-header :columns="queryColumns" @change="onQueryParamsChange" @submit="onSubmit" @reset="onReset">
<template v-for="item in queryColumns" :key="item.prop" v-slot:[item.prop]="{ query }">
<slot :name="`${item.prop}Query`" :query="query" />
</template>
<template #handleMenu>
<slot name="handleMenu" />
</template>
</query-header>
<!-- 表格 -->
<el-table ref="tableView" :data="list" :loading="loading" @selection-change="onSelectionChange">
<!-- 表格选择 -->
<el-table-column type="selection" width="55" v-if="props.selection" />
<!-- 展开行内容 -->
<el-table-column type="expand" v-if="expand">
<template #default="{ row }">
<slot name="expand" :row="row" />
</template>
</el-table-column>
<!-- 表格列 -->
<el-table-column
v-for="column in tableColumnsList"
:key="column.prop"
:align="column.align ? column.align : 'center'"
:label="column.label"
:prop="column.prop"
:width="column.width"
:sortable="column.sortable"
show-overflow-tooltip
>
<template #default="scope">
<slot :name="column.prop" :row="scope.row">
{{ scope.row[column.prop] }}
</slot>
</template>
</el-table-column>
<!-- 操作菜单 -->
<slot name="tableMenu" />
</el-table>
</div>
<!-- 分页 -->
<el-pagination
v-model:current-page="queryForm.page_no"
v-model:page-size="queryForm.page_size"
:page-sizes="[1, 10, 20, 50, 100]"
background
:background="background"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="onPageSizeChange"
@current-change="onPageChange"
class="mt20 flex"
style="justify-content: flex-end"
/>
</template>
<script setup>
import request from "@/utils/request"
import QueryHeader from "./QueryHeader.vue"
import { ref, reactive, onMounted, watch } from "vue"
/* 父组件传递参数
apiUrl: { type: String, required: true }, // 请求地址
tableColumns: { type: Array, required: true }, // 表格列
selection: { type: Boolean, default: false }, // 是否可多选
rowKey: { type: String, default: '' }, // 行数据的 Key,用来优化 Table 的渲染;
expand: { type: Boolean, default: false }, // 是否可展开
*/
const props = defineProps(["apiUrl", "tableColumns", "expandable", "selection", "rowKey", "expand"])
const tableView = ref(null)
const queryColumns = ref([])
const tableColumnsList = ref([])
watch(
() => props.tableColumns,
(newVal, oldVal) => {
queryColumns.value = newVal.filter((item) => {
return item.search
})
tableColumnsList.value = newVal.filter((item) => {
return !item.hide
})
}
)
onMounted(() => {
queryColumns.value = props.tableColumns.filter((item) => {
return item.search
})
tableColumnsList.value = props.tableColumns.filter((item) => {
return !item.hide
})
getList()
})
/* 获取列表数据 */
const loading = ref(false)
const total = ref(0)
const list = ref([])
const queryForm = reactive({
page_no: 1,
page_size: 10,
})
function getList() {
loading.value = true
let params = JSON.parse(JSON.stringify(queryForm))
request
.get({
url: props.apiUrl,
params,
})
.then((res) => {
list.value = res.lists
total.value = res.count
loading.value = false
})
}
/* */
/* 表格分页页数切换 */
function onPageChange(num) {
queryForm.page_no = num
getList()
}
/* 表格每页数量切换 */
function onPageSizeChange(num) {
queryForm.page_size = num
queryForm.page_no = 1
getList()
}
/* 重置查询 */
function queryList(dataList) {
/* dataList除query-header 外查询参数 */
if (dataList && dataList.length > 0) {
for (let item of dataList) {
queryForm[item.key] = item.value
}
}
queryForm.page_no = 1
getList()
}
/* 表格选择 */
const emit = defineEmits(["select"])
function onSelectionChange(value) {
emit("select", value)
}
/* 查询条件-点击查询按钮 */
function onSubmit() {
queryList()
}
/* 查询条件-参数变化 */
function onQueryParamsChange(value) {
Object.assign(queryForm, value)
}
/* 查询条件-清空参数 */
function onReset(value) {
Object.assign(queryForm, value)
queryList()
}
/* 暴露到父组件方法 */
defineExpose({
queryList,
})
</script>
页面引用
<template>
<div class="app-container home">
<query-table ref="tableViewRef" apiUrl="/adviser/lists" :table-columns="tableColumns" :selection="true">
<!-- 筛选条件自定义 -->
<template #create_timeQuery="{ query }">
<el-date-picker
v-model="query.create_time"
type="daterange"
value-format="YYYY-MM-DD"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="onTimeChange"
/>
</template>
<template #is_disableQuery="{ query }">
<el-select v-model="query.is_disable" clearable>
<el-option label="是" :value="1"></el-option>
<el-option label="否" :value="0"></el-option>
</el-select>
</template>
<template #handleMenu>
<el-row>
<el-col :span="12">
<el-space>
<el-button type="primary" icon="Plus" @click="clickAdd('')" v-perms="['adviser/add']">添加</el-button>
<el-button>批量导入</el-button>
<el-button>批量导出</el-button>
</el-space>
</el-col>
</el-row>
</template>
<!-- table自定义列 -->
<template #is_disable="{ row }">
<el-switch v-model="row.is_disable" :active-value="1" :inactive-value="0"></el-switch>
</template>
<template #tableMenu>
<el-table-column label="操作" align="center" width="200">
<template #default="{ row }">
<router-link :to="`./info?id=${row.id}`">
<el-button type="primary" link>详情</el-button>
</router-link>
<!-- <el-button v-perms="['adviser/edit']" type="primary" link @click="clickAdd(row.id)">
编辑
</el-button>
<el-button v-perms="['adviser/delete']" type="danger" link @click="handleDelete(row.id)">
删除
</el-button> -->
</template>
</el-table-column>
</template>
</query-table>
</div>
</template>
<script setup name="Index">
import QueryTable from "@/components/QueryTable/index.vue"
const tableColumns = [
{ label: "顾问名称", prop: "name", search: true },
{ label: "手机号", prop: "mobile", search: true },
{ label: "微信号", prop: "user_id" },
{ label: "关联用户数", prop: "adviser_id", width: 150 },
{ label: "当前面试", prop: "commission", sortable: true },
{ label: "预约单", prop: "w_commission", sortable: true },
{ label: "服务单", prop: "wz_commission", sortable: true },
{ label: "创建时间", prop: "create_time", width: 160, search: true },
{ label: "是否启用", prop: "is_disable", search: true },
]
</script>
<style scoped lang="scss"></style>
原文地址:https://blog.csdn.net/qq_40476712/article/details/145278573
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!