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

news2024/11/24 16:28:49

前言

为什么需要二次封装

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

为什么需要定制化

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

需要了解的前置知识

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

来看实现效果

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

看看效果

image.png

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

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

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

数据可视化(四):Pandas技术的高级操作案例,豆瓣电影数据也能轻松分析!

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

(八)Pandas窗口数据与数据读写 学习简要笔记 #Python #CDA学习打卡

一. 窗口数据(Window Functions) Pandas提供了窗口函数(Window Functions)用于在数据上执行滑动窗口操作&#xff0c;可以对数据进行滚动计算、滑动统计等操作。需要注意的是&#xff0c;在使用窗口函数时&#xff0c;需要根据实际需求选择合适的窗口大小和窗口函数&#xff0…

硬件设备杂记——12G SDI及 AES67/EBU

常见的 SDI线缆规格&#xff0c;HD-SDI又被称为1.5G-SDI&#xff0c;具体参数以秋叶原的参数为例 AES67/EBU 目前音频网络标准主要集中在OSI网络体系的第二层和第三层。 第二层音频标准的弊端在于构建音频网络时需要专用的交换机&#xff0c;无法利用现有的以太网络&#xff0c…

布局香港之零售中小企篇 | 传承之味,迈向数字化经营的时代

随着内地与香港两地经贸合作日渐紧密&#xff0c;越来越多内地消费品牌将目光投向香港这片充满机遇的热土&#xff0c;纷纷入驻香港市场。「北店南下」蔚然成风&#xff0c;其中不乏已在内地市场深耕多年的传统老字号。数字化经营时代&#xff0c;老字号焕新刻不容缓&#xff0…

QoS流量整形

流量整形是一种带宽技术形式&#xff0c;它延迟某些类型的网络数据包的流动&#xff0c;以确保更高优先级应用程序的网络性能&#xff0c;它主要涉及调整数据传输速率&#xff0c;以确保网络资源以最佳容量得到利用。流量整形的目的是防止网络拥塞并提高网络的整体性能&#xf…

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

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

C++:深入理解operator new/operator delete

动态内存管理 1.语法层面1.基本语法注意点 2.new/delete和malloc/free的区别3.operator new和operator delete函数&#xff08;底层重点&#xff09;1.operator new/delete原理2.图解1.new/new[]2.delete/delete[] 3.new[n]和delete[] 4.定位new1.定义2.使用格式 1.语法层面 1…

EPSON晶振应用到汽车电子产品上的型号有哪些?

EPSON品牌应用在汽车电子产品上的晶振.&#xff0c;当然也少不了晶振可能最熟悉的就是32.768K系列和26MHZGPS晶振用的多。 在汽车里每一个部件都应有的不一样,甚至多次使用到同一尺寸,不同频率的晶振.爱普生品牌晶振型号就有几百种,很容易混淆,要想记住汽车里所应用到的不是件…

python爬虫(Selenium案列)第二十四

&#x1f388;&#x1f388;作者主页&#xff1a; 喔的嘛呀&#x1f388;&#x1f388; &#x1f388;&#x1f388;所属专栏&#xff1a;python爬虫学习&#x1f388;&#x1f388; ✨✨谢谢大家捧场&#xff0c;祝屏幕前的小伙伴们每天都有好运相伴左右&#xff0c;一定要天天…

windows docker desktop==spark环境搭建

编写文件docker-compose.yml version: 3services:spark-master:image: bde2020/spark-master:3.1.1-hadoop3.2container_name: spark-masterports:- "8080:8080"- "7077:7077"- "2220:22"volumes:- F:\spark-data\m1:/dataenvironment:- INIT_D…

HiveSql中的函数家族(二)

一、窗口函数 1、什么是窗口函数 在 SQL 中&#xff0c;窗口函数&#xff08;Window Functions&#xff09;是一种特殊的函数&#xff0c;它允许在查询结果集的特定窗口&#xff08;通常是一组行&#xff09;上执行聚合、分析和计算操作&#xff0c;而无需聚合整个结果集。窗口…

Linux 2.进程(守护进程)

守护进程 何谓守护进程常见守护进程进程查看命令pskill命令编写简单守护进程守护进程的父进程 何谓守护进程 daemon&#xff0c;表示守护进程&#xff0c;简称为d&#xff08;进程名后面带d的基本就是守护进程&#xff09; 长期运行&#xff08;一般是开机运行直到关机时关闭&…

Flask项目在Pycharm中设置局域网访问

打开PyCharm导入本应用。点击Run标签中的Edit Configurations 其中Target type选择Script path&#xff0c;Target填入本项目中app.py的路径&#xff0c;Additional optional填入--host0.0.0.0(不要有空格)。 再重新运行项目&#xff0c;会观察到除了原本的http://127.0.0.1:50…

java在线问卷调查系统的设计与实现(springboot+mysql源码+文档)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的在线问卷调查系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于java的在线问卷调查…

函数 基础知识

本笔记为观看 50 函数-函数的定义_哔哩哔哩_bilibili的学习笔记 1 函数概述 作用:将一段经常使用的代码封装起来&#xff0c;减少重复代码一个较大的程序&#xff0c;一般分为若干个程序块&#xff0c;每个块实现特定的功能。 2 函数的定义 eg: int max(int a,int b); {retu…

社交媒体数据恢复:钉钉

在数字化办公日益普及的今天&#xff0c;钉钉作为一款综合性的企业级通讯工具&#xff0c;已经深入到众多企业和个人的工作与生活中。然而&#xff0c;在日常使用过程中&#xff0c;我们难免会遇到一些意外情况导致数据丢失的问题。本文将针对钉钉数据恢复这一主题&#xff0c;…

windows下python opencv ffmpeg读取摄像头实现rtsp推流 拉流

windows下python opencv ffmpeg读取摄像头实现rtsp推流 拉流 整体流程1.下载所需文件1. 1下载rtsp推流服务器1.2 下载ffmpeg2. 开启RTSP服务器3. opencv 读取摄像头并调用ffmpeg进行推流4. opencv进行拉流整体流程 1.下载所需文件 1. 1下载rtsp推流服务器 下载 RTSP服务器 下…

pyqt+opencv+常用图像算法可视化[资源介绍]

包含的算法&#xff1a; 均值滤波高斯滤波中值滤波Sobel边缘检测Laplacian边缘检测Canny边缘检测膨胀腐蚀灰度化直方图均衡化 包含的功能&#xff1a; 从文件中打开图片返回上一张处理后的图像保存处理后的图像文件退出系统 系统界面&#xff1a; 见我的资源&#xff0c;ht…

大型网站系统架构演化实例_3.使用服务集群改善网站并发处理能力

1.使用服务集群改善网站并发处理能力 使用集群是网站解决高并发、海量数据问题的常用手段。当一台服务器的处理能力、存储空间不足时&#xff0c;不要企图去更换更强大的服务器&#xff0c;对大型网站而言&#xff0c;不管多么强大的服务器&#xff0c;对大型网站而言&…