前端新手Vue3+Vite+Ts+Pinia+Sass项目指北系列文章 —— 第十一章 基础界面开发 (组件封装和使用)

前言

Vue 是前端开发中非常常见的一种框架,它的易用性和灵活性使得它成为了很多开发者的首选。而在 Vue2 版本中,组件的开发也变得非常简单,但随着 Vue3 版本的发布,组件开发有了更多的特性和优化,为我们的业务开发带来了更多便利。本文将介绍如何使用 Vue3 开发业务组件,并通过代码实例进行演示。

一、自己封装组件

1、button 代码

src 目录下创建 components 文件夹,并在该文件夹下创建 Button 文件。
Button 文件中创建 index.vue 文件和 index.ts 文件,并编写以下代码
index.vue 文件中编写以下代码

<script lang="ts" setup name="ZButton">
defineProps({text: {type: String,default: ''},btnSize: {type: String,default: 'default'},size: {type: Number,default: 14},type: {type: String,default: 'default'},left: {type: Number,default: 0},right: {type: Number,default: 0},disabled: {type: Boolean,default: false},loading: {type: Boolean,default: false}
})
</script><template><div :type="type" :size="btnSize" :class="`z-button-${type}`" :disabled="disabled" :loading="loading" :style="{marginLeft: `${left}px`,marginRight: `${right}px`}">{{ text }}</div>
</template><style lang="scss" scoped>
.z-button-blue {background: #80d4fb;color: #fff;border: none;&:hover,&:focus,&:active {background: #80d4fb80;color: #fff;}.anticon {color: #fff;}
}.z-button-warn {background: #ec622b;color: #fff;border: none;outline: none;&:hover,&:focus,&:active {background-color: #ec622b80;color: #fff;}.anticon {color: #fff;}
}
</style>

index.ts 文件中编写以下代码

import ZButton from "./index.vue";export default ZButton

2、button 使用组件

我们在 home 页面导入组件来进行测试

<script setup lang="ts">
import { useRouter } from 'vue-router'
import useUserStore from '@/store/modules/user'
import ZButton from '@/components/Button/index' // 新增const router = useRouter()
const userStore = useUserStore()function goRouter(path: string): void {router.push(path)
}function getUserInfo(): void {console.log(userStore.userInfo, 'userStore.userInfo')
}
</script><template><div class="flex-c flex-align h-100"><el-button type="primary" @click="goRouter('/news')">go news</el-button><el-button type="primary" @click="goRouter('/user')">go user</el-button><el-button @click="getUserInfo">get user info</el-button><el-button type="primary" @click="goRouter('/table')">go table</el-button><!-- 新增 --><z-button type="blue" text="测试blue" :left="10"></z-button><!-- 新增 --><z-button type="warn" text="测试warn" :left="10"></z-button></div>
</template>

3、button 效果图

在这里插入图片描述

二、基于 Element-Plus 封装组件

1、table 代码

components 文件夹下创建 Table 文件。

Table 文件中创建 index.vueindex.tstypes.ts 文件,并编写以下代码
index.vue 文件中编写以下代码

<script setup lang="ts" name="ZTable">
import { ref, computed, watch, nextTick, defineExpose } from 'vue'
import { ElTable } from 'element-plus'
import { ZTableOptions } from './types'const props = withDefaults(defineProps<{// 表格配置选项propList: ZTableOptions[]// 表格数据data: any[]// 表格高度height?: string | numbermaxHeight?: string | number// 显示复选框showSelectColumn?: boolean// 显示复选框showExpand?: boolean// 显示序号showIndexColumn?: boolean// 显示操作columnoperation?: boolean// 操作column 宽度operationWidth?: stringmoreOperationsPopoverWidth?: string// 加载状态loading?: boolean// 加载文案loadingText?: string// 加载图标名elementLoadingSpinner?: string// 是否显示分页pagination?: boolean// 显示分页的对齐方式paginationAlign?: 'left' | 'center' | 'right'pageInfo?: any// 显示分页数据多少条的选项pageSizes?: number[]// 数据总条数total?: numberemptyImg?: boolean}>(),{propList: () => [],height: '100%',operation: true,operationWidth: '240px',moreOperationsPopoverWidth: '160px',paginationAlign: 'right',pageInfo: () => ({ page: 1, size: 10 }),pageSizes: () => [10, 15, 20, 30],total: 0,emptyImg: true}
)const ZTableRef = ref<InstanceType<typeof ElTable>>()
const tablePropList: any = ref([])watch(() => props.propList,(list) => {tablePropList.value = []nextTick(() => {tablePropList.value = JSON.parse(JSON.stringify(list))})},{immediate: true}
)// 表格分页的排列方式
const justifyContent = computed(() => {if (props.paginationAlign === 'left') return 'flex-start'else if (props.paginationAlign === 'right') return 'flex-end'else return 'center'
})const emits = defineEmits(['row-click','select-rows','page-change','sort-change','operation-click'
])const handleOperationClick = (row: any, code: string, index: number) => {emits('operation-click', code, row, index)
}
const selectable = (row: any, index: any) => {return !row.noSelectable
}
const handleRowClick = (row: any, column: any) => {if (column?.label == '操作') returnemits('row-click', row, column)
}
const handleSelectionChange = (list: any) => {emits('select-rows', list)
}
const handleSizeChange = (size: number) => {emits('page-change', { page: 1, size })
}
const handleCurrentChange = (page: number) => {emits('page-change', { ...props.pageInfo, page })
}
const changeTableSort = (value: any) => {emits('sort-change', value)
}
const toggleSelection = (rows?: any) => {if (rows) {rows.forEach((row: any) => {ZTableRef.value!.toggleRowSelection(row, true)})} else {ZTableRef.value!.clearSelection()}
}defineExpose({toggleSelection
})
</script><template><div class="z-table"><el-table :data="data" :height="height" :max-height="maxHeight" ref="ZTableRef" v-loading="loading":element-loading-text="loadingText" :element-loading-spinner="elementLoadingSpinner" stripe@sort-change="changeTableSort" @row-click="handleRowClick" @selection-change="handleSelectionChange"v-bind="$attrs"><template #empty v-if="emptyImg"><div class="empty-box"><el-empty></el-empty></div></template><el-table-column type="expand" v-if="showExpand"><template #default="scope"><slot name="baseExpandSlot" :row="scope.row"></slot></template></el-table-column><el-table-column v-if="showSelectColumn" type="selection" :selectable="selectable" fixed="left" align="center"width="55"></el-table-column><el-table-column v-if="showIndexColumn" fixed="left" type="index" label="序号" align="center"width="55"></el-table-column><template v-for="propItem in tablePropList" :key="propItem.prop"><template v-if="propItem.visible !== false"><template v-if="!propItem.slotName"><el-table-column v-bind="propItem"></el-table-column></template><template v-else><el-table-column v-bind="propItem"><template #default="scope"><slot :name="propItem.slotName" :format="propItem.dateFormat" :row="scope.row" :prop="propItem.prop":index="scope.$index"></slot></template></el-table-column></template></template></template><el-table-column v-if="operation" label="操作" :width="operationWidth" fixed="right"><template #default="scope"><template v-if="scope.row.operations"><div class="operations-wrap"><template v-for="(o, i) in scope.row.operations" :key="o.code"><el-button v-if="i < 3" text type="primary" size="small" :disabled="o.disabled"@click="handleOperationClick(scope.row, o.code, scope.$index)">{{ o.name }}</el-button></template><el-popover placement="bottom-end" :width="moreOperationsPopoverWidth"v-if="scope.row.operations.length > 3"><template #reference><el-icon color="#26A5FF" class="more-dot"><MoreFilled /></el-icon></template><div class="more-operations"><template v-for="(o, i) in scope.row.operations" :key="o.code"><el-button v-if="i > 2" text type="primary" size="small" :disabled="o.disabled" @click="handleOperationClick(scope.row, o.code, scope.$index)">{{ o.name }}</el-button></template></div></el-popover></div></template></template></el-table-column></el-table><div v-if="pagination" class="pagination" :style="{ justifyContent }"><el-pagination small :current-page="pageInfo.page" :page-sizes="pageSizes" :page-size="pageInfo.size"layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange"@current-change="handleCurrentChange"></el-pagination></div></div>
</template><style lang="scss" scoped>
.operations-wrap {.el-button+.el-button {margin-left: 25px;}.more-dot {position: relative;top: 0.3em;margin-left: 25px;font-size: 20px;cursor: pointer;}
}.more-operations {display: flex;flex-wrap: wrap;.el-button {overflow: hidden;margin-left: 10px;height: 32px;border-radius: 8px;line-height: 32px;}
}.el-loading-mask {z-index: 1;
}.pagination {display: flex;margin-top: 16px;
}.el-table__expand-column .cell {width: 55px;
}.is-dark {max-width: 40%;
}
</style>

index.ts 文件中编写以下代码

import ZTable from './index.vue'export default ZTable

types.ts 文件中编写以下代码

export interface ZTableOptions {// 是否可见visible?: boolean// 自定义列模板的插槽名slotName?: string// 日期格式化dateFormat?: string// 表头label: string// 字段名称prop?: string// 对应列的宽度width?: string | numberminWidth?: string | number// 对齐方式align?: 'left' | 'center' | 'right'fixed?: true | 'left' | 'right'showOverflowTooltip?: booleansortable?: boolean | 'custom'
}

2、table 组件使用

table 文件中下添加 index.vue 并添加对应路由文件,编写以下代码

<script lang="ts" setup>
import ZTable from '@/components/Table/index'
import { ref } from 'vue'
import { ZTableOptions } from '@/components/Table/types'const tableData: any = ref([{fileName: '测试文件01',fileType: 'pdf',submitterName: '张三',submitTime: '2024-01-04 09:34:18'},{fileName: '测试文件02',fileType: 'png',submitterName: '李四',submitTime: '2024-01-04 11:26:57'}
])const propList: ZTableOptions[] = [{showOverflowTooltip: true,label: '文件名称',prop: 'fileName',minWidth: 130,align: 'left'},{showOverflowTooltip: true,label: '文件类型',prop: 'fileType',minWidth: 130,align: 'left'},{label: '上传人',prop: 'submitterName',minWidth: 150,showOverflowTooltip: true},{label: '上传时间',prop: 'submitTime',minWidth: 160}
]
</script><template><div><z-table :propList="propList" :data="tableData" :operation="false"></z-table></div>
</template><style scoped lang="scss">
</style>

3、table 效果图

在这里插入图片描述

总结

通过以上的介绍和代码实例,我们可以看到 Vue3 提供了更多的特性和优化,让我们更加方便地开发业务组件。在实际开发中,我们可以根据实际需求选择合适的组件开发方式,并通过 Vue3 的特性来提升开发效率。希望本文能够帮助到你在 Vue3 开发中的业务组件开发。上文中的配置代码可在 github 仓库中直接 copy,仓库路径:https://github.com/SmallTeddy/ProjectConstructionHub。

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

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

相关文章

第十四章[面向对象]:14.1:类和实例

一,认识面向对象编程 1,什么是面向对象编程? 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。 2,面向对象最重要的两个概念就是类(Class)和实例(Instance) 类是抽象的…

戴尔Dell R740服务器开机冒烟亮黄灯故障维修

今天分享的是一台过保修期的DELL PowerEdge R740服务器开机冒烟的维修案例。先上图&#xff1a; 接到用户报修后工程师立即响应&#xff0c;由于用户也是刚开工第一天服务器开机就出现了这种祥龙吐雾的祥兆&#xff0c;导致工厂业务流程无法正常使用&#xff0c;这台机器在东莞…

【Linux取经路】文件系统之重定向的实现原理

文章目录 一、再来理解重定向1.1 输出重定向效果演示1.2 重定向的原理1.3 dup21.4 输入重定向效果演示1.5 输入重定向代码实现 二、再来理解标准输出和标准错误2.1 同时对标准输出和标准错误进行重定向2.2 将标准输出和标准错误重定向到同一个文件 三、再看一切皆文件四、结语 …

RK3588平台开发系列讲解(视频篇)ffmpeg 的移植

文章目录 一、ffmpeg 介绍二、ffmpeg 的组成三、ffmpeg 依赖库沉淀、分享、成长,让自己和他人都能有所收获!😄 📢ffmpeg 是一种多媒体音视频处理工具,具备视频采集功能、视频抓取图像、视频格式转换、给视频加水印并能将视频转化为流等诸多强大的功能。它采用 LGPL 或 G…

「Java同步原理与底层实现解析」

原理概要&#xff1a; java虚拟机中的同步基于进入与结束Monitor对象实现&#xff0c;无论是显式同步&#xff08;同步代码块进入在jvm是根据monitorenter标志、结束是monitorexit标志&#xff0c;那最后一个是monitorexit是异常结束时被执行的释放指令&#xff09;、隐式同步…

c++学习第十七讲---STL常用容器---list容器

list容器&#xff1a; 一、list基本概念&#xff1a; list容器&#xff1a;一个双向循环链表。 注&#xff1a;list和vector是两个最常用的容器&#xff0c;各有优缺点。 二、list构造函数&#xff1a; list<T> lst; //默认构造 list(b…

力扣算法Algorithm竞赛模板库(codeforces-go):含了算法竞赛中常用的数据结构和算法实现,助力开发者更高效地解决问题

1.算法Algorithm竞赛模板库&#xff08;codeforces-go&#xff09; 算法竞赛模板库&#xff0c;为算法竞赛爱好者提供了一系列精心设计的算法模板。这个库包含了算法竞赛中常用的数据结构和算法实现&#xff0c;助力开发者更高效地解决问题 一个算法模板应当涵盖以下几点&…

k8s学习(RKE+k8s+rancher2.x)成长系列之简配版环境搭建(四)之Helm及cert-manager安装

安装Helm(三台都安装) 下载helm安装包并加入执行目录 tar zxf helm-v3.2.4-linux-amd64.tar.gz cd linux-amd64 cp helm /usr/bin/ helm version添加rancher稳定版仓库(三台都安装) helm repo add rancher-stable http://rancher-mirror.oss-cn-beijing.aliyuncs.com/serve…

【Kotlin】Kotlin流程控制

1 选择结构 Kotlin 中选择结构主要包含 if -else、when 语句&#xff0c;并且可以返回结果。 1.1 if-else 1.1. 条件选择 fun main() {var score 85if (score > 90) {println("优秀")} else if (score > 80) {println("良好")} else if (score &…

知识蒸馏实战代码教学二(代码实战部分)

一、上章原理回顾 具体过程&#xff1a; &#xff08;1&#xff09;首先我们要先训练出较大模型既teacher模型。&#xff08;在图中没有出现&#xff09; &#xff08;2&#xff09;再对teacher模型进行蒸馏&#xff0c;此时我们已经有一个训练好的teacher模型&#xff0c;所以…

人工智能_普通服务器CPU_安装清华开源人工智能AI大模型ChatGlm-6B_001---人工智能工作笔记0096

使用centos安装,注意安装之前,保证系统可以联网,然后执行yum update 先去更新一下系统,可以省掉很多麻烦 20240219_150031 这里我们使用centos系统吧,使用习惯了. ChatGlm首先需要一台个人计算机,或者服务器, 要的算力,训练最多,微调次之,推理需要算力最少 其实很多都支持C…

openEuler学习——mysql(第一次总结)

1、openEuler 二进制方式安装MySQL 8.0.x。 思路是先从官网获取安装包链接如下https://mirrors.aliyun.com/mysql/MySQL-8.0/mysql-8.0.28-linux-glibc2.12-x86_64.tar.xz 然后解压安装修改权限&#xff0c;可以参考mysql官方网站步骤 [rootopenEuler-node1 ~]# wget -c https:…