前端新手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.mzph.cn/news/691437.shtml

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

相关文章

css pointer-events 多层鼠标点击事件

threejs 无法滑动视角&#xff0c;菜单界面覆盖threejs操作事件。 pointer-events /* Keyword values */ pointer-events: auto; pointer-events: none; pointer-events: visiblePainted; /* SVG only */ pointer-events: visibleFill; /* SVG only */ pointer-events: visib…

Python中HTTP请求的基本方法:穿越网络的魔法咒语

在网络世界中&#xff0c;HTTP请求就像是对服务器的“魔法咒语”&#xff0c;它能让我们的Python程序与远方的服务器进行沟通&#xff0c;获取或发送数据。今天&#xff0c;我们就来聊聊Python中HTTP请求的基本方法&#xff0c;看看这些“咒语”是如何施展的。 首先&#xff0…

java数据结构与算法刷题-----LeetCode155. 最小栈

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 1. 法一&#xff1a;使用辅助最小栈 解题思路&#xff1a;时间复杂度O(1)…

自己怎么做小程序?如何通过小程序赚钱?如何确保产品有竞争力?

引言 随着科技的迅速发展&#xff0c;小程序已经成为创业者们进军电商领域的一种重要途径。在这个数字时代&#xff0c;通过小程序卖东西已经成为一种便捷而高效的商业模式。本文将为您解析自己如何通过小程序销售商品&#xff0c;并实现盈利的关键步骤。无论您是初入创业圈的…

ClickHouse 基础(一)

官网 以毫秒为单位查询数十亿行 ClickHouse是用于实时应用和分析的最快、资源效率最高的开源数据库。 安装ClickHouse 使用ClickHouse&#xff0c;你有三个选择: ClickHouse云:官方ClickHouse作为一项服务&#xff0c;-由ClickHouse的创建者构建&#xff0c;维护和支持快速安…

Hadoop-Yarn-调度器总结

一、Yarn有哪些调度器 在cdh中Yarn组件中查看配置如下&#xff1a; 可以看到Yarn有三种调度器&#xff0c;分别是FairScheduler、FifoScheduler、CapacityScheduler&#xff0c;它们都是Hadoop的一个可插入调度器。 cdh默认的调度器是FairScheduler&#xff0c;hadoop默认的调…

Linux-目录I/O-004

学习重点&#xff1a; 1.目录I/O的函数接口 2.目录的遍历&#xff0c;目录的递归遍历 1.【mkdir】 1.1函数原型 【int mkdir(const char *pathname, mode_t mode);】1.2函数功能 创建目录文件1.3函数参数 1.3.1【pathname】 文件路径1.3.2【mode】 文件的权限1.4返回值 …

【Java EE初阶二十】关于http(一)

1. 初识http HTTP 最新的版本应该是 HTTP/3.0&#xff0c;目前大规模使用的版本 HTTP/1.1&#xff1b; 下面来简单说明一下使用 HTTP 协议的场景: 1、浏览器打开网站 (基本上) 2、手机 APP 访问对应的服务器 (大概率) 前面的 TCP与UDP 和http不同&#xff0c;HTTP 的报文格式&a…

【conda环境 安装 tensorflow2.2】 解决方案

1.检查anaconda安装&#xff1a;在cmd输入 conda --version 2.检测已经安装的环境&#xff1a;conda info --envs 3.新建一个python3.5的环境&#xff0c;tensorflow&#xff1a; ###conda create -n xxx python3.5 xxx为虚拟环境名 ###conda create -n xxx python3.6 xxx为虚拟…

openGauss 5.0.0全密态数据库应用小试

前言 openGauss HCIA教材中&#xff0c;安全是一个重要的章节&#xff0c;在实际项目中&#xff0c;随着网络安全和信息安全形势的变化&#xff0c;企业也越来越重视数据库安全。去年在HALP内部进行openGauss培训时&#xff0c;安全特性就被学员们提出来要重点讲解&#xff0c…

SICTF Round#3 Web方向 题解WP

100&#xff05;_upload 题目描述&#xff1a;小茂夫说&#xff1a;一直上传恶意文件尊嘟要生气了&#xff0c;世事莫固守&#xff0c;转变思路求突破 开题&#xff0c;注意有个文件包含 题目把后缀过滤死了&#xff0c;无法上传php后缀文件。文件内容些许过滤&#xff0c;短…

在ubuntu20.04 上配置 qemu/kvm linux kernel调试环境

一&#xff1a;安装qemu/kvm 和 virsh qemu/kvm 是虚拟机软件&#xff0c;virsh是管理虚拟机的命令行工具&#xff0c;可以使用virsh创建&#xff0c;编辑&#xff0c;启动&#xff0c;停止&#xff0c;删除虚拟机。 &#xff08;1&#xff09;&#xff1a;安装之前&#xff0c…

LLM应用开发与落地:chroma的近似搜索问题

背景 最近开始测试一个游戏客户的RAG模块&#xff0c;发现一个向量数据库中大家容易忽略的一个点&#xff1a;近邻搜索算法。一开始我们选择的是chroma作为向量数据库&#xff0c;因为chroma的用户接口和设计非常简单&#xff0c;而我偏向于简单。创建collection时设置的距离计…

EasySass: could not generate CSS file. See Output panel for details.微信小程序报错及解决

解决微信小程序导入vscode的easysass包报错 问题发现问题来源和解决制作不易&#xff0c;感谢三联&#xff0c;谢谢大家啦 问题发现 当我喜滋滋的在vscode中导入easysass包之后&#xff0c;又在微信小程序中添加vscode扩展&#xff0c;又去文件中改好了配置文件后却直接弹出了…

npm run dev运行出现NODE_OPTIONS=--max_old_space_size=4096 vite --mode dev --host?

问题描述 PS E:\AWorkDataease\DataEase\core\core-frontend> npm run dev dataease0.0.0 dev NODE_OPTIONS–max_old_space_size4096 vite --mode dev --host 0.0.0.0 ‘NODE_OPTIONS’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 解决方案 遇到…

生成对抗网络----GAN

系列文章目录 文章目录 系列文章目录前言一、基本构成二、应用领域三、基本原理四、如何训练GAN 前言 一、基本构成 GAN (Generative Adversarial Network) : 通过两个神经网络&#xff0c;即生成器&#xff08;Generator&#xff09;和判别器&#xff08;Discriminator&#…

AtCoder Beginner Contest 341 D - Only one of two (Java)

AtCoder Beginner Contest 341 D - Only one of two (Java) 比赛链接&#xff1a;AtCoder Beginner Contest 341 D题传送门AtCoder&#xff1a;D - Only one of two D题传送门洛谷&#xff1a;[ABC341D] Only one of two 题目&#xff1a;[ABC341D】 Only one of two 题目…

安卓游戏开发之图形渲染技术优劣分析

一、引言 随着移动设备的普及和性能的提升&#xff0c;安卓游戏开发已经成为一个热门领域。在安卓游戏开发中&#xff0c;图形渲染技术是关键的一环。本文将对安卓游戏开发中常用的图形渲染技术进行分析&#xff0c;比较它们的优劣&#xff0c;并探讨它们在不同应用场景下的适用…

python+django+vue汽车票在线预订系统58ip7

本课题使用Python语言进行开发。基于web,代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中 使用说明 使用Navicat或者其它工具&#xff0c;在mysql中创建对应名称的数据库&#xff0c;并导入项目的sql文件&#xff1b; 使用PyChar…

好书推荐丨《细说机器学习:从理论到实践》

文章目录 写在前面机器学习推荐图书内容简介编辑推荐作者简介 推荐理由粉丝福利写在最后 写在前面 本期博主给大家推荐一本有关机器学习的全新正版书籍&#xff0c;对机器学习、人工智能感兴趣的小伙伴们快来看看吧~ 机器学习 机器学习&#xff08;Machine Learning, ML&…