Vue3和ElementPlus封装table组件

最近学习vue3.2并自己在写一个项目,然后发现好几个页面都是列表页,重复写table和column也是觉得累,学习的项目列表页不算多,要是公司项目就不一样了,所以就想着自己封装一个table组件,免去大量重复工作和copy改改改。

本文也是仅仅封装了一个相对简单的table组件,主要是table + 分页,要是不想要分页,也是可以通过使用table组件穿参数控制是否展示分页。基于查询表单,后续再安排~

封装一个table组件并不难,主要是搞懂插槽、作用域插槽的写法和用法,下面先复习一下插槽,再进行封装。

一、slot插槽

定义

Vue 实现了一套内容分发的 API,将 元素作为承载分发内容的出口。

简单理解:就是对子组件的扩展,通过 插槽向子组件内部指定位置传递内容。

插槽是组件的一块HTML模板,这块模板显示不显示,怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制。

分类

  • 匿名插槽
  • 具名插槽
  • 作用域插槽

匿名插槽

它不用设置名称属性,可以放置在组件的任意位置;可以理解为父传入样式及内容,子负责展示

<!--index.vue-->
<Child ><ul><li>1</li><li>2</li></ul><ul slot><li v-for="(v,i) in arr" :key="i">{{v}}</li></ul>
</Child><!--child.vue-->
<!--匿名插槽-->
<template><div><slot></slot></div>
</template>

具名插槽

插槽加了名称属性,就变成了具名插槽。 在 v-slot 之后添加冒号 (:) ,然后写出要传递内容的 slot 的名称(v-slot:slotname);简写:#slotname

<!--index.vue-->
<Child><template #default> <!--指定了 default 的名称,表示不需要为默认插槽指定名称;--><p>我是main的内容</p> </template><template #header><h2>艾梯哎教育</h2></template><template #list><h2>列表展示</h2><ul><li v-for="(v,i) in arr" :key="i">{{v}}</li></ul></template>
</Child><!--child.vue-->
<!--具名插槽-->
<slot></slot>
<slot name="header"></slot>
<slot name="list"></slot>

作用域插槽

好理解的叫法:带数据的插槽。

作用域插槽跟单个插槽和具名插槽的区别,因为单个插槽和具名插槽不绑定数据,所以父组件提供的模板一般要既包括样式又包括内容,而作用域插槽,相当于父组件提供一套样式,数据都是子组件的。

<!--index.vue-->
<Child ><template #user="obj"><h2>老师:{{ obj.user.username }}</h2> <h2>所授课程:{{ obj.user.course }}</h2></template><!--解构写法--><template #user="{user}"><h2>老师:{{ user.username }}</h2> <h2>所授课程:{{ user.course }}</h2> </template><!--解构别名--><template #user="{user:person}"><h2>老师:{{ person.username }}</h2> <h2>所授课程:{{ person.course }}</h2> </template></Child><!--child.vue-->
<template><div><slot name="user" :user="user"></slot> </div>
</template><script setup>
import {ref,reactive} from 'vue'
const user = ref({id:1,username:'张老师',course:'vue'});
</script>

二、封装table

理解了具名作用域插槽 之后,相信大家脑海里已经有思路如何封装了。我这里的思路大概如下:

  • 接收tableData数据和columns列以及其他杂七杂八的配置项;
  • 然后在el-table-column上循环columns列;
  • 然后定义以列名为名称的插槽,并将数据row传递出去;
  • 并提供默认插槽内容,当没特殊数据展示,可不传父的内容,直接使用 定义的默认内容;
  • 如果 columns传入fommater,则会根据传入的function进行转换数据。

具体实现如下:

<!--MyTable-->
<template><div><el-table :style="{ width: '100%' }"ref="elTableRef":data="tableData" :height="height" :max-height="maxHeight":stripe="stripe":row-key="rowKey":highlight-current-row="highlightCurrentRow"@row-click="handleRowClick"@selection-change="handleSelectionChange"><el-table-column v-for="item in columns" :key="item.prop":prop="item.prop" :label="item.label":show-overflow-tooltip="item.showOverflowTooltip":width="item.width":fixed="item.fixed":type="item.type":sortable="item.sortable":selectable="item.selectableFn"><!-- type 对应列的类型。 如果设置了selection则显示多选框; --><!-- 如果设置了 index 则显示该行的索引(从 1 开始计算); --><!-- 如果设置了 expand 则显示为一个可展开的按钮--><!-- selection / index / expand --><template #default="{row, column, $index}" v-if="item.type==='index'">{{getIndex($index)}}</template><template #default="{row, column, $index}" v-if="!item.type"><!-- 具名作用域插槽 --><slot :name="item.prop":slotProps="row":index="$index"><!-- 默认内容,当父组件不传内容时默认显示该内容 --><span v-if="item.formatter">{{ item.formatter(row[item.prop]) }}</span><span v-else>{{ row[item.prop] }}</span></slot></template></el-table-column></el-table><div class="pagination-wrap"><el-paginationv-if="hasPagination"v-model:current-page="currentPage"v-model:page-size="pageSize":page-sizes="pageSizes":small="small":background="true":layout="layout":total="total"@size-change="handleSizeChange"@current-change="handleCurrentChange"/></div></div>
</template><script setup>
import {toRefs} from 'vue'
const props = defineProps({// 表格相关tableData: {type: Array,default: []},columns:{type: Array,default: []},height: {type: String,default: '500px'},maxHeight: {type: String,default: '500px'},stripe: {type: Boolean,default: true},rowKey: {type: String,default: 'id'},highlightCurrentRow: {type: Boolean,default: true},//  分页相关hasPagination: {type:Boolean,default: true},total: {type: Number,default: 0},currentPage: {type: Number,default: 1},pageSize: {type:Number,default: 10},pageSizes: {type: Array,default: [10, 20, 50, 100, 200]},layout: {type: String,default: 'total, sizes, prev, pager, next, jumper'},small: {type: String,default: 'small'}
})let {tableData,columns,height,maxHeight,stripe,rowKey,highlightCurrentRow,hasPagination,total,currentPage,pageSize,pageSizes,layout,small
} = toRefs(props)const emit = defineEmits(['rowClick','selectChange','changeTableData','update:currentPage','update:pageSize'])
// 当某一行被点击时会触发该事件
const handleRowClick = (row, column, event) => {emit('rowClick', { row, column, event })
}
// 当选择项发生变化时会触发该事件
const handleSelectionChange = (selection) => {emit('selectChange', selection)
}// 每页条数变化的事件
const handleSizeChange = (val) => {emit('update:pageSize',val)emit('changeTableData', currentPage.value, val)
}
// 当前页码变化的事件
const handleCurrentChange = (val) => {emit('update:currentPage',val)emit('changeTableData', val, pageSize.value)
}const getIndex = (index)=> {return index + 1 + (currentPage.value - 1) * pageSize.value
}</script><style lang="scss" scoped></style>

三、使用MyTable组件

因为check需要格式化内容并且用el-tag来进行展示内容,所以此处向table组件传入了需要展示的内容,此时,向table的name=check的插槽传入内容,那么table组件的默认展示内容则失效。

同理,由于每个taable组件的操作项也不一样,所以此处向name=operator的slot插入内容。

<MyTable :tableData="tableData":columns="columns":total="total":currentPage="listQuery.pageNo":pageSize="listQuery.pageSize"@changeTableData="changeTableData"><template #check="{ slotProps }"><el-tag class="ml-2" :type="slotProps.check?'success':'danger'">{{ checkFilter(slotProps.check) }}</el-tag></template><template #operator="{slotProps}"><el-button type="primary" @click="setData('edit',slotProps)">编辑</el-button><el-button type="danger" @click="handleDel(slotProps)">删除</el-button></template>
</MyTable><script setup>
import { ref,onMounted } from 'vue'
import MyTable from '@/components/table/index.vue'
import useHooks from '@/hooks'const { checkFilter, dateFormate } = useHooks()let listQuery = ref({pageNo:1,pageSize: 10
})
const tableData = ref([])
let total = ref(0)/*** prop:数据项列名* label:列名展示名* fixed:固定列 true/right/left* width:列宽* show-overflow-tooltip* type:对应列的类型 selection / index / expand* sortable:true/false* selectable:Function* formatter:格式化内容 function(row, column, cellValue, index)
**/
let columns = ref([{prop: 'number',label: '车牌自编号'},{prop: 'numberplate',label: '车牌号'},{prop: 'date',label: '出厂日期',formatter: dateFormate},{prop: 'check',label: '车辆状态'},{prop: 'operator',label: '操作',fixed: "right"},
])onMounted(() => {getCarList()
})const changeTableData = (pageNum,pageSize) => {listQuery.value.pageNo = pageNumlistQuery.value.pageSize = pageSizegetCarList()
}// 列表查询
async function getCarList() {const {data: {data}} = await carList(listQuery.value)tableData.value = data.listtotal.value = data.rows
}</script>

效果如下:

 

cef83f1ca276458da478452ec7772e20.png如果需要加上索引或者复选框,需要在columns上添加上

 

    {type: 'selection',label:'',width: '50px'},{type: 'index',label:'序号',width: '60px'},

若是列项超长不需要tooltip,则配置showOverflowTooltip为false(默认是true)

    {prop: 'number',label: '车牌自编号',showOverflowTooltip: true, width: '100px'},

 

113407b2c8dd4584a369f61df475b6f0.png到此一个talbe组件就封装完成,如有不当的地方还请大家多多包含和赐教!如大家有不一样的封装思想也多多留言交流,互相学习互相进步。

 

 

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

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

相关文章

滑动窗口

题目 思路 对于一个数组区间的最值&#xff0c;可以开辟一个队列记录&#xff08;当然这里不能叫队列只是和队列相似&#xff0c;习惯性叫法)。 每个区间的最值等于队首元素。扫描数组时&#xff0c;如果该元素大于队尾元素&#xff08;取最大值时&#xff09;将该队尾元素出队…

DM数据库学习之路(二十)DM8基于主备集群技术的两地三中心集群部署及测试(全网最详细)

DM两地三中心介绍 摘要 金融行业对数据的可靠性和连续性有着极其严格的要求,任何数据丢失或服务中断都可能导致严重的经济损失。针对这一问题,基于达梦主备集群技术的两地三中心解决方案能够切实有效解决业务数据的可靠性和连续性需求。该方案通过构建两个数据中心和一个灾备…

解密Lawnchair:打造个性化极致的Android桌面体验

解密Lawnchair&#xff1a;打造个性化极致的Android桌面体验 1. 简介 Lawnchair是一款知名的Android桌面定制工具&#xff0c;旨在为用户提供个性化极致的桌面体验。作为一个开源项目&#xff0c;Lawnchair融合了简洁、灵活和强大的特点&#xff0c;让用户能够自由定制其Andro…

Python | Conda安装包报错:PackagesNotFoundError

Conda在下载安装包时报错&#xff1a; PackagesNotFoundError: The following packages are not available from current channels:- XXXXXX&#xff08;包名&#xff09;有如下两种解决方法&#xff1a; 方法一&#xff1a;将conda-forge添加到搜索路径上 在命令行运行下方指令…

深入理解C语言:开发属于你的三子棋小游戏

三子棋 1. 前言2. 准备工作3. 使用二维数组存储下棋的数据4. 初始化棋盘为全空格5. 打印棋盘6. 玩家下棋7. 电脑下棋8. 判断输赢9. 效果展示10. 完整代码 1. 前言 大家好&#xff0c;我是努力学习游泳的鱼&#xff0c;今天我们会用C语言实现三子棋。所谓三子棋&#xff0c;就是…

Android 开发环境搭建的步骤

本文将为您详细讲解 Android 开发环境搭建的步骤。搭建 Android 开发环境需要准备一些软件和工具&#xff0c;以下是一些基础步骤&#xff1a; 1. 安装 Java Development Kit (JDK) 首先&#xff0c;您需要安装 Java Development Kit (JDK)。JDK 是 Android 开发的基础&#xf…

【Android 内存优化】怎么理解Android PLT hook?

文章目录 前言什么是hook?PLT hook作用基本原理PLT hook 总体步骤 代码案例分析方案预研面临的问题怎么做&#xff1f;ELFELF 文件头SHT&#xff08;section header table&#xff09; 链接视图&#xff08;Linking View&#xff09;和执行视图&#xff08;Execution View&…

YOLO-World 简单无需标注无需训练直接可以使用的检测模型

参考: https://github.com/AILab-CVC/YOLO-World YOLO-World 常规的label基本不用训练,直接传入图片,然后写入文本label提示既可 案例demo: 1)官方提供 https://huggingface.co/spaces/stevengrove/YOLO-World https://huggingface.co/spaces/SkalskiP/YOLO-World 检测…

基于信息间隙决策理论的碳捕集电厂优化调度程序代码!

适用平台&#xff1a;MatlabYalmipCplex 程序在建立电厂与碳捕集装置协同调度模型的基础上&#xff0c;引入信息间隙决策理论(information gap decision theory, IGDT)以同时满足系统的鲁棒性和经济性要求&#xff0c;通过风险追求和风险规避&#xff12;种决策角度得到不同的…

真不愧是华为出来的,真的太厉害了。。。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 实习去了博彦科技&#xff08;外包&#xff09;&#xff0c;做的就是螺丝钉的活&#xff0c;后面…

华为---MSTP(一)---MSTP生成树协议

目录 1. MSTP技术产生背景 2. STP/RSTP的缺陷 ​编辑 2.1 无法均衡流量负载 2.2 数据使用次优路径 3. MSTP生成树协议 3.1 MSTP相关概念 3.2 MSTP树生成的形成过程 4. MSTP报文 1. MSTP技术产生背景 RSTP在STP基础上进行了改进&#xff0c;实现了网络拓扑快速收敛。但…

SpringBoot+Maven项目打包

项目的主POM文件里面添加maven打包插件 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.2</version><configuration><sour…

推荐一款新的自动化测试框架:DrissionPage

今天给大家推荐一款基于Python的网页自动化工具&#xff1a;DrissionPage。这款工具既能控制浏览器&#xff0c;也能收发数据包&#xff0c;甚至能把两者合而为一&#xff0c;简单来说&#xff1a;集合了WEB浏览器自动化的便利性和 requests 的高效率优点。 一、DrissionPage框…

【C++庖丁解牛】默认成员函数

&#x1f4d9; 作者简介 &#xff1a;RO-BERRY &#x1f4d7; 学习方向&#xff1a;致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f4d2; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;欢迎各位关注&#xff0c;谢谢各位的支持 目录 前言1. 构造函数1.1 …

职场高薪 |「中高级测试」面试题

【软件测试面试突击班】2024吃透软件测试面试最全八股文攻略教程&#xff0c;一周学完让你面试通过率提高90%&#xff01;&#xff08;自动化测试&#xff09; 一.基础题 1.测试用例你一般是怎么设计的&#xff0c;怎么可以提高覆盖率&#xff1f; 有没有形成自己的 一套方法论…

Jmeter接口测试---随机数、加密、cookie鉴权、断言、CSV参数化

随机数 第一步&#xff1a;选择工具-函数助手对话框 第二步&#xff1a;选择random&#xff0c;设置最大值最小值&#xff0c;复制函数字符串到指定位置 加密接口 类型&#xff1a;AES、DES、Base64、RSA&#xff08;可以解密&#xff09; | MD5、SHA、HmacSHA&#xff08;不…

llama.c代码2

1、forward 1.1、复习 encode(tokenizer, prompt, 1, 0, prompt_tokens, &num_prompt_tokens); 在encode函数结尾处(gdb) p *n_tokens $3 2(gdb) p *tokens3 $6 {1, 22172, 417} 在encode调用后 (gdb) print num_prompt_tokens $11 2 (gdb) print *prompt_tokens3 $13 …

JavaScript 中的类型转换机制(详细讲解)

文章目录 一、概述二、显示转换Number()parseInt()String()Boolean() 三、隐式转换自动转换为布尔值自动转换成字符串自动转换成数值 一、概述 前面我们讲到&#xff0c;JS中有六种简单数据类型&#xff1a;undefined、null、boolean、string、number、symbol&#xff0c;以及…

(sub)三次握手四次挥手

TCP的三次握手与四次挥手理解及面试题 序列号seq&#xff1a;占4个字节&#xff0c;用来标记数据段的顺序&#xff0c;TCP把连接中发送的所有数据字节都编上一个序号&#xff0c;第一个字节的编号由本地随机产生&#xff1b;给字节编上序号后&#xff0c;就给每一个报文段指派一…

(学习日记)2024.03.03:UCOSIII第五节:常用汇编指令+OS初始化+启动任务+任务切换

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…