赞
踩
前言
开发后台管理系统,会接触到很多表格和表单,一但表格表单多起来,仅仅只需要一小部分改变,都需要在中重写一大堆代码,许多重复逻辑,我们可以把重复逻辑抽离
出来二次封装一个组件
使用,减少在开发中需要编写的代码。
每个项目或业务都有自己的特点和需求,可能需要特定的样式、交互行为或功能。通过定制化组件,可以根据具体需求进行定制提高复用性
,使得组件更符合业务场景,而且定制化可以使组件更加贴近实际业务需求。
vue3中插槽slot与template
v-bind的使用
v-bind=“$attrs”
el-table的基本属性
这是一个el-plus基础表格
//Hytable.vue <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> const tableData = [ { date: '2016-05-03', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-02', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-04', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, { date: '2016-05-01', name: 'Tom', address: 'No. 189, Grove St, Los Angeles', }, ] </script>
//HyTable.vue <template> <el-table :data="tableData" style="width: 100%"> <el-table-column prop="date" label="Date" width="180" /> <el-table-column prop="name" label="Name" width="180" /> <el-table-column prop="address" label="Address" /> </el-table> </template> <script lang="ts" setup> import requestTabledata from '../api/index.ts' interface TableProps{ requestApi?: (params: any) => Promise<any>; } // 接受父组件参数,配置默认值 const props = withDefaults(defineProps<TableProps>(), { requestApi: requestTableData }); let tableData= ref([]) const getTableList = async (api:any) => { let { data } = await api(); tableData.value = data }; onMounted(() => { getTableList(props.requestApi) }) </script>
我们先来看下table-column的属性
这里我们可以用\<template>来包裹el-table-column组件再用v-for来遍历
为什么要使用<template>来包裹,因为等下需要根据列配置用v-if判断el-table-column是否存在列配置type或prop属性,父组件需要传递列配置。
//HyTable.vue <template> <el-table :data="tableData" style="width: 100%" row-key="id"> <template v-for="item in columnData" :key="columnData.item"> <el-table-column v-if="item.type && ['selection','index','expand'].includes(item.type)" v-bind="item" :align="'center'" :reserve-selection="item.type == 'selection'"> <template #default="scope"> <template v-if="item.type === 'expand'"> <slot :name="item.type" v-bind="scope" /> </template> </template> </el-table-column> <el-table-column v-if="!item.type && item.prop" v-bind="item" :align="'center'" > <template #default="scope"> <slot :name="item.prop" v-bind="scope" :row="scope.row"> {{ scope.row[item.prop] }} </slot> </template> </el-table-column> </template> </el-table> </template> <script setup lang="ts" name="Hytable"> import { onMounted, ref } from "vue"; import {requestTableData} from "../../api/index.ts" interface TableProps{ columns: any, requestApi?: (params?: any) => Promise<any>; } const props = withDefaults(defineProps<TableProps>(), { columns: [], requestApi: requestTableData }); // 将列设置响应化 const columnData = ref(props.columns); let tableData= ref([]) const getTableList = async (api:any) => { let { data } = await api(); tableData.value = data }; onMounted(() => { getTableList(props.requestApi) }) </script>
<template> <el-table :data="tableData" style="width: 100%"> <template v-for="item in columnData" :key="columnData.item"> <el-table-column v-if="item.type && ['selection','index','expand'].includes(item.type)" v-bind="item" :align="'center'" :reserve-selection="item.type == 'selection'"> <template #default="scope"> <template v-if="item.type === 'expand'"> <slot :name="item.type" v-bind="scope" /> </template> </template> </el-table-column> <el-table-column v-if="!item.type && item.prop" v-bind="item" :align="'center'" > <template #default="scope"> <slot :name="item.prop" v-bind="scope" :row="scope.row"> {{ scope.row[item.prop] }} </slot> </template> </el-table-column> </template> <!-- 这是el-table组件自带的插槽 --> <template #append> <slot name="append" /> </template> <!-- 无数据 --> <template #empty> <div class="table-empty"> <slot name="empty"> <div>暂无数据</div> </slot> </div> </template> </el-table> </template>
让我们来使用一波
//父组件 <template> <Hytable :columns="columnData" > <template #expand="scope"> {{scope.row}} </template> <template #gender="scope"> <el-button type="primary" plain> {{ scope.row.gender}} </el-button> </template> <template #operation> <el-button type="primary" link :icon="View" >查看</el-button > <el-button type="primary" link :icon="EditPen" >编辑</el-button > <el-button type="primary" link :icon="Delete" >删除</el-button > </template> </HyTable> </template> <script setup lang="ts"> import Hytable from '../components/testTable/index.vue'; import {Delete, EditPen, View} from "@element-plus/icons-vue"; import { ElMessage} from "element-plus"; const columnData = [ { type: 'selection', fixed: 'left', width: 70 }, { type: 'expand', label: 'Expand', width: 80 }, { prop: 'name', label: '姓名', search: { el: 'input' } }, { prop: 'email', label: '邮箱' }, { prop: 'address', label: '居住地址' }, { prop:'gender', label: '性别'}, {prop: 'state', label:'用户状态'}, { prop: 'operation', label: '操作', fixed: 'right', width: 300 }, ] </script>
来看实现效果
// Hytable.vue <template> ... <el-table-column v-if="!item.type && item.prop" v-bind="item" :align="'center'" show-overflow-tooltip="showOverflowTooltip"> <template #default="scope"> <slot :name="item.prop" v-bind="scope" :row="scope.row"> {{ scope.row[item.prop] }} </slot> </template> </el-table-column> ... <slot name="pagination" v-if="pagination"> <el-pagination :background="true" :current-page="pageable.pageNum" :page-size="pageable.pageSize" :page-sizes="[10, 25, 50, 100]" :total="pageable.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange" > </el-pagination> </slot> </template> <script setup lang="ts"> import { onMounted, ref } from "vue"; import {requestTableData} from "../../api/index.ts" import { reactive } from "vue"; import { toRefs } from "vue"; import { computed } from "vue"; interface TableProps{ columns: any, requestApi?: (params?: any) => Promise<any>; pagination?: boolean, showOverflowTooltip?: boolean; } const props = withDefaults(defineProps<TableProps>(), { columns: [], requestApi: requestTableData, pagination: true, showOverflowTooltip:true, }); const columnData = ref(props.columns); // let tableData= ref([]) onMounted(() => { getTableList(props.requestApi) }) const handlePage:()=>any = ()=>{ const state = reactive({ tableData: [], pageable: { pageNum:1, pageSize:10, total: 0, } }) const getTableList = async (api:any) => { let { data } = await api(); state.tableData = data state.pageable.total = data.length }; const handleSizeChange = (val:any) => { state.pageable.pageNum = 1; state.pageable.pageSize = val; getTableList(props.requestApi) } const handleCurrentChange = (val: any) => { state.pageable.pageNum = val; getTableList(props.requestApi) } // pageable.total = data return{ ...toRefs(state), getTableList, handleSizeChange, handleCurrentChange, } } const {tableData,pageable,handleSizeChange,handleCurrentChange,getTableList} = handlePage() const processTableData = computed(() => { if (!props.pagination) return tableData.value return tableData.value.slice( pageable.value.pageNum - 1) * pageable.value.pageSize, pageable.value.pageSize * pageable.value.pageNum ) }) </script>
看看效果
额。。。还有很多可以加的比如增删改查、查询表单慢慢更新吧
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。