️️️Vue3+Element-Plus二次封装一个可定制化的table组件

前言

为什么需要二次封装

开发后台管理系统,会接触到很多表格和表单,一但表格表单多起来,仅仅只需要一小部分改变,都需要在中重写一大堆代码,许多重复逻辑,我们可以把重复逻辑抽离出来二次封装一个组件
使用,减少在开发中需要编写的代码。

为什么需要定制化

每个项目或业务都有自己的特点和需求,可能需要特定的样式、交互行为或功能。通过定制化组件,可以根据具体需求进行定制提高复用性,使得组件更符合业务场景,而且定制化可以使组件更加贴近实际业务需求。

需要了解的前置知识

vue3中插槽slot与template

v-bind的使用

v-bind=“$attrs”

el-table的基本属性

不多废话,创建文件Hytable,开始代码

这是一个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>

一般的表格数据(TableData)是在父组件中请求返回的

//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>

我们可以看到el-table-column有很多重复的代码,如何让他根据父组件的传递值来动态的生成列的配置呢

我们先来看下table-column的属性
image.png
这里我们可以用\<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-columnv-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-buttontype="primary"link:icon="View">查看</el-button><el-buttontype="primary"link:icon="EditPen">编辑</el-button><el-buttontype="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>

来看实现效果

image.png

基本封装已经可以了,接下来可以增加些功能 如滚动条和内容溢出处理

// 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 = datastate.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 = datareturn{...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>

看看效果

image.png

额。。。还有很多可以加的比如增删改查、查询表单慢慢更新吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/630702.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详解 C++ 实现K-means算法

一、K-means算法概述 K-means算法是一种非常经典的聚类算法,其主要目的是将数据点划分为K个集群,以使得每个数据点与其所属集群的中心点(质心)的平方距离之和最小。这种算法在数据挖掘、图像处理、模式识别等领域有着广泛的应用。 二、K-means算法的基本原理 K-means算法…

原来是这样的Three.js,我悟了

最近在b站上面看到up主&#xff1a;gamemcu的3D作品&#xff0c;着实让人感到非常震撼&#xff0c;作品中的SU7模型&#xff0c;利用的是Blender进行建模&#xff0c;利用了webGL的技术进行开发。由此启发了我对3D极大的乐趣。因此&#xff0c;凭借一点点&#x1f90f;的前端知…

3ds Max2024安装包(亲测可用)

目录 一、软件简介 二、软件下载 一、软件简介 3ds Max是一款基于PC系统的强大3D建模、渲染和制作软件&#xff0c;广泛应用于游戏开发、影视后期制作、建筑设计、工业设计等多个领域。其拥有丰富的建模工具&#xff0c;可轻松创建逼真的三维场景和模型&#xff1b;同时&#…

搜维尔科技:【工业仿真】煤矿机械安全事故VR警示教育系统

产品概述 搜维尔科技 煤矿机械安全事故VR警示教育系统 系统内容&#xff1a; 系统采用虚拟现实技术模拟矿井井下机械安全技术及事故&#xff0c;展现井下常见机械伤害事故&#xff0c;表现伤害事故的隐患点&#xff0c;能够模拟事故发生和发展过程&#xff1b;营造井下灾害发…

【AI工具之Prezo如何自动生成PPT操作步骤】

先说优缺点&#xff1a; 最大的优点就是免费&#xff08;但说实话功能和体验方面很弱&#xff09;支持中文提问&#xff08;最好用英文&#xff09;&#xff0c;智能生成图文&#xff08;但是只能生成英文内容&#xff09;可以AI生成图片&#xff0c;图片很精美酷炫&#xff0…

2024年服务器上安装Cacti教程

监控您的服务器是管理服务器的关键步骤&#xff0c;可以保证您有准确的数据来观看服务器的运行状况。您可以查看开源监控服务查看可用的许多免费选项。 本问将向您展示如何在服务器上安装Cacti。 此外&#xff0c;它将向您展示如何访问Web门户并启动配置以监视服务器的运行状况…

页缓存(PageCache)和预读机制(readahead )

页缓存&#xff08;PageCache)和预读机制&#xff08;readahead &#xff09; 页缓存&#xff08;PageCache)是操作系统&#xff08;OS&#xff09;对文件的缓存&#xff0c;用于加速对文件的读写。 page 是内存管理分配的基本单位&#xff0c; Page Cache 由多个 page 构成&…

【Leetcode每日一题】 分治 - 排序数组(难度⭐⭐)(60)

1. 题目解析 题目链接&#xff1a;912. 排序数组 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 2.算法原理 算法思路&#xff1a; 快速排序作为一种经典的排序算法&#xff0c;其核心思想在于通过“分而治之”的策略&#xff…

hbase-2.2.7分布式搭建

一、下载上传解压 1.在官网或者云镜像网站下载jar包 华为云镜像站&#xff1a;Index of apache-local/hbase/2.2.7 2.上传到linux并解压 tar -zxvf hbase-2.2.7-bin.tar.gz -C /usr/locol/soft 二、配置环境变量 1. vim /etc/profile export HBASE_HOME/usr/local/soft/h…

线性代数---行列式的性质

1. 行列式的行与列(按原顺序)互换

Ansible在macOS上的安装部署

一、安装 Ansible&#xff08;使用 Homebrew&#xff09; 安装 Homebrew&#xff08;如果尚未安装&#xff09;&#xff1a; /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"使用 Homebrew 安装 Ansible&#x…

OpenHarmony网络请求库-httpclient

简介 HTTP是现代应用程序通过网络交换数据和媒体的的主要方式。httpclient是OpenHarmony 里一个高效执行的HTTP客户端&#xff0c;使用它可使您的内容加载更快&#xff0c;并节省您的流量。httpclient以人们耳熟能详的OKHTTP为基础&#xff0c;整合android-async-http&#xf…