️️️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-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.mfbz.cn/a/556218.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Springboot Gateway 报错Failed to resolve “bogon”的原因及解决办法

一、问题出现原因及初步分析 今天遇到一个奇怪的错误&#xff0c;一个一直正确运行的微服务后台&#xff0c;突然无法访问&#xff0c;如何重启都会报错。 想到近期有人在服务器上安装过其它服务&#xff0c;因此&#xff0c;考虑可能是配置问题&#xff0c;可配置问题修复后…

Ubuntu 传输文件

scp [选项] 源文件 目标路径 以下是一些常用的 scp 命令选项&#xff1a; -r&#xff1a;递归复制目录和子目录。 -P&#xff1a;指定远程 SSH 服务器的端口号。 -i&#xff1a;指定用于身份验证的私钥文件。 -p&#xff1a;保留源文件的时间戳、权限和所有者。 -v&#x…

从D盘调整空间增加到C盘而不丢失数据的3 种方法

越来越多的Windows 10笔记本电脑和台式机使用SSD作为系统盘&#xff0c;这对于提高计算机性能很有用&#xff0c;因为SSD的读写速度要快得多。但另一方面&#xff0c;SSD价格更高&#xff0c;因此比传统机械硬盘体积更小。当然C盘空间不足的可能性更大。在这种情况下&#xff0…

Java学习笔记零基础入门1

目录 第一章 Java概述 1.1 什么是程序 1.2 Java 技术体系平台 1.3 Java 重要特点 1.4 Java 的开发工具 4.1 工具选择 1.5 Java 运行机制及运行过程 5.1 Java 语言的特点&#xff1a;跨平台性 5.2 Java 核心机制-Java 虚拟机 [JVMjavavirtual machine] 1.6 什么是JDK&…

K8s 部署 elasticsearch-7.14.0 集群 及 kibana 客户端

一、K8s 部署 elasticsearch-7.14.0 集群 安装规划 组件replicas类型es3StatefulSetkibana1Deployment 使用 k8s 版本为&#xff1a;v1.18.0 。 本次使用 OpenEBS 来作为存储引擎&#xff0c;OpenEBS 是一个开源的、可扩展的存储平台&#xff0c;它提供了一种简单的方式来创…

HQL,SQL刷题,尚硅谷(中级)

目录 相关表结构&#xff1a; 1、order_info表 2、order_detail表 题目及思路解析&#xff1a; 第一题&#xff0c;查询各品类销售商品的种类数及销量最高的商品 第二题 查询用户的累计消费金额及VIP等级 第三题 查询首次下单后第二天连续下单的用户比率 总结归纳&#xff1a…

2024.4.18

学生管理部分 #include<myhead.h> int main(int argc, char *argv[]) {sqlite3* ppDbNULL;if(sqlite3_open("./mydb.db",&ppDb)!SQLITE_OK){printf("sqlite3_open error:%s\n",sqlite3_errmsg(ppDb));return -1;}//创建数据表char arg[128]&quo…

SQL Serve---嵌套查询

定义 嵌套查询&#xff1a;主要用于复杂的查询中。在SQL语言中&#xff0c;一个Select From Where语句称为一个查询块&#xff0c;将一个查询块嵌套在另一个查询的Where子句或Having短语中的查询称为嵌套查询。 子查询的类型 使用别名的子查询 使用IN和NOT IN的子查询 使用比较…

4.15报错记录

打开文件时出错a bytes-like object is required,notNoneType 确保E:/data/stdata/st- images-1208-json|ST-WT-1.json是一个有效的标签文件。 今天用X-anylabling更改标签目录时出现这个报错 解决方案&#xff1a;图片文件夹中创建同名的一个文件夹把json文件放进去就可以打…

Ubuntu 微调训练ChatGLM3大语言模型

Ubuntu 微调训练ChatGLM3大语言模型 LLaMA Factory 的 LoRA 微调提供了 3.7 倍的加速比&#xff0c;同时在广告文案生成任务上取得了更高的 Rouge 分数。结合 4 比特量化技术&#xff0c;LLaMA Factory 的 QLoRA 微调进一步降低了 GPU 显存消耗。 https://github.com/hiyouga…

六边形酷科技特效单页源码

源码介绍 基于canvas画布绘制多个六边形追踪鼠标&#xff0c;科技感的几何图形酷炫动画特效&#xff0c; 单页html源码&#xff0c;可以做网站动态背景&#xff0c;喜欢的朋友可以拿去 效果截图 完整源码 <!doctype html> <html> <head> <meta charset…

OpenHarmony UI开发-ohos-svg

简介 ohos-svg是一个SVG图片的解析器和渲染器&#xff0c;解析SVG图片并渲染到页面上。它支持大部分 SVG 1.1 规范&#xff0c;包括基本形状、路径、文本、样式和渐变,它能够渲染大多数标准的 SVG 图像。ohos-svg的优点是性能好、内存占用低。 效果展示 SVG图片解析并绘制: …

C++ | Leetcode C++题解之第35题搜索插入位置

题目&#xff1a; 题解&#xff1a; class Solution { public:int searchInsert(vector<int>& nums, int target) {int n nums.size();int left 0, right n - 1, ans n;while (left < right) {int mid ((right - left) >> 1) left;if (target < n…

单页面首屏优化,打包后大小减少64M,加载速度快了13.6秒

需求背景 从第三方采购的vue2 ElementUI实现的云管平台&#xff0c;乙方说2011年左右就开始有这个项目了&#xff08;那时候有Vue了吗&#xff0c;思考.jpg&#xff09;。十几年的项目&#xff0c;我何德何能可以担此责任。里面的代码经过多人多年迭代可以用惨不忍睹来形容&a…

面试题:Java中int符号数字的位运算与操作 + 原码、反码、补码之间如何进行转换

题目来源 阿里-淘天-技术1面 问题 -1和4做位运算与操作&#xff0c;结果是多少&#xff1f; 答案 正确答案 4 通过Java代码验证如下&#xff1a; 我的回答 -5&#xff0c;但是-5是错误的答案。 面试的时候&#xff0c;面试官没有告诉我对错。 为什么&#xff1f; 到底…

[生活][杂项] 上班党的注意事项

前言 目前是上班已经接近两年了&#xff0c;目前的状态是&#xff0c;一个人租了一个单间在上班。对于这种情况有以下几点需要注意。 钥匙问题&#xff0c;一定不要陷入钥匙丢失的情况&#xff01;一定不要陷入钥匙丢失的情况&#xff01;一定不要陷入钥匙丢失的情况&#xff…

CSS:filter(滤镜)属性

用途 可以用于img标签&#xff0c;div标签等 图像&#xff0c;背景&#xff0c;边框的调整 常用属性 1. 灰度 grayscale()&#xff0c;默认是0&#xff0c;100%就是黑白 2. blux 给图像设置高斯模糊的程度&#xff0c;radius值设定高斯模糊的程序&#xff0c;表示像素点…

2024年Q1季度冰箱行业线上市场销售数据分析

Q1季度冰箱线上市场表现不如预期。 根据鲸参谋数据显示&#xff0c;2024年1月至3月线上电商平台&#xff08;京东天猫淘宝&#xff09;冰箱累计销量约410万件&#xff0c;环比下降11%&#xff0c;同比下降21%&#xff1b;累计销售额约98亿元&#xff0c;环比下降31%&#xff0…

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

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

详细分析Python的继承和多态(附Demo)

目录 前言1. 继承2. 多态 前言 入行多年&#xff0c;对于知识点还会混淆&#xff0c;此处主要做一个详细区分 继承&#xff08;Inheritance&#xff09;: 面向对象编程中的一个重要概念&#xff0c;允许一个类&#xff08;称为子类或派生类&#xff09;继承另一个类&#xff…
最新文章