『精』Vue 组件如何模块化抽离Props
『精』Vue 组件如何模块化抽离Props
文章目录
- 『精』Vue 组件如何模块化抽离Props
- 一、为什么要抽离Props
- 二、选项式API方式抽离
- 三、组合式API方式抽离
- 3.1 TypeScript类型方式
- 3.2 文件分离方式
- 3.3 对文件分离方式优化
- 参考资料💘
- 推荐博文🍗
一、为什么要抽离Props
在前端框架中封装一个组件是非常常见的,对于组件来讲,往往离不开组件之间属性的传递,通过属性能够控制组件的样式内容、处理逻辑类型、数据传递。假如有这么一个用于签名的组件,能够控制画笔的大小、颜色、画布背景颜色宽高、按钮的文案提示等,那么它的属性必定是有十几个选项,假设 800 行代码里可能就得花费 100 行去声明这些属性,这明显是不合适的。
这也是我为什么提议要抽离组件 Props 的原因,实际上这个签名组件也确实存在,源自于我在 Uniapp 插件市场上的一个提交。
抽离Props的好处有这么几点:
- 降低、隔离组件的复杂度,降低维护成本与提高程序可靠率。
- 引入一个中间的、易于理解的抽象概览。
- 隐藏非核心处理部分的实现细节,提高组件源码的可阅读性。
- 促进代码的重用,包装一定的结构风范。
- 属性的抽离,有助于自动化程序生成对应文档。
那么要怎么做才能抽离出 Props 呢,在 Vue 身上根据选项式 API 和组合式 API 写法的不同,做法也不一样。
一些简单的组件可能只有一两个属性,甚至是没有属性,对于这种情况下,可能不抽离 Props 会显得更方便一些,但一定要注意的是应当把组件以后要做的和其扩展维护性放在一起考虑,往往十几个属性堆叠的组件都是从一两个属性的组件开始的,既然以后会越加越多,那为何不提早抽离处理方便以后再加呢,当然具体怎么做取决于自己。
二、选项式API方式抽离
选项式 API 适用于 Vue2 和 Vue3,需要使用到 Mixins 混合方法。Mixins 不只是能抽离 Props,它能做到更多,我相信大部分对这个功能会比较熟悉,有兴趣的可以参考此文档 Mixins。
import type { PropType } from "vue";export default {props: {prop1: {type: String,required: true},prop2: {type: Array as PropType<string[]>,default: ["a", "b", "c"]},prop3: {type: Array as PropType<Record<string, unknown>[]>,defalue: []}}
};
<script lang="ts">import props from "./props";export default {mixins: [props]};</script>
三、组合式API方式抽离
组合式 API 属性的声明依赖于 defineProps
编译宏,这个编译宏只能出现在 .vue 的文件中才能正确识别,那么对于 Hook 来说,抽离 Props 是行不通的。
3.1 TypeScript类型方式
defineProps
是支持 typescript 类型标注声明的,直接引入一个类型行不行得通的呢?关于这个问题要分 Vue3.3 版本之前与之后,Vue3.3 版本之前是不允许将类型接口以导入的形式传给 defineProps
泛型,在官方文档中也有对应的标注,相关讨论在这 issue。
但这还有一个问题,typescript只能声明类型,如果要配置默认值的话需要搭配另外一个编译宏 withDefaults
去实现,且类型接口能导入还好,若是不能导入的话,本地类型接口又违背降低复杂度而抽离的初衷了,在我看来还不如不用。依据 Vue3.3 版本之后,可以参考下列示例:
export interface Props {prop1: string;prop2?: string[];prop3?: Record<string, unknown>[];
}export const propsDefault = {prop1: "默认值",prop2: () => ["a", "b", "c"]
};
<template><div>{{ $props.prop1 }}</div><div>{{ $props.prop2 }}</div>
</template><script lang="ts" setup>import { type Props, propsDefault } from "./props";const $props = withDefaults(defineProps<Props>(), propsDefault);</script>
3.2 文件分离方式
人们往往容易把简单的东西想复杂,将 Props 类型声明存放到一个单独文件里,只要确保 defineProps
在 .vue 文件中使用即可,这么做有个好处就是简单易用且在不依赖typescript的时候基本兼容 Vue3 各版本,对于我来讲,我更习惯于使用 文件分离式 进行 Props 的抽离。
这种方式与 Hook 不同的是,Hook需要一层函数包裹执行,而这样相当于直接引入配置文件中的一个变量。
import type { PropType } from "vue";export const props = {prop1: {type: String,required: true},prop2: {type: Array as PropType<string[]>,default: ["a", "b", "c"]},prop3: {type: Array as PropType<Record<string, unknown>[]>,defalue: []}
};
<template><div>{{ $props.prop1 }}</div><div>{{ $props.prop2 }}</div>
</template><script lang="ts" setup>const $props = defineProps(props);</script>
对于 TypeScript 如果需要获取 Props 的类型,那就需要用到 Vue 的一个辅助类型 ExtractPropTypes
,对于外部引用(父组件)的话使用 ExtractPublicPropTypes
,只需在上面示例的基础上改造一下👇。
import type { PropType, ExtractPropTypes } from "vue";export const props = {prop1: {type: String,required: true},prop2: {type: Array as PropType<string[]>,default: ["a", "b", "c"]},prop3: {type: Array as PropType<Record<string, unknown>[]>,defalue: []}
};// 导出 Props 类型
export type Props = ExtractPropTypes<typeof props>;
其实 ElementUI 的源码也是这么去做的,以 el-empty 组件为例,源码中对于属性的分离是这么写的。
3.3 对文件分离方式优化
从优化的角度上看,Vue 的Props声明方式都是一样的,同样的代码写多次显得有些冗余,那不妨将这些 Props 声明再次优化一下,编写一个公共的 Props 辅助工具进行声明。
"use strict";
/*** 组件属性辅助* 🙌 能够使用更少的代码编写,有助于减少包体积*/
import type { PropType } from "vue";export const unknownProp = null as unknown as PropType<unknown>;export const numericProp = [Number, String];export const truthProp = {type: Boolean,default: true as const
};export const lieProp = {type: Boolean,default: false as const
};export const makeRequiredProp = <T>(type: T) => {return { type, required: true as const };
};export const makeNumericProp = <T>(defVal: T) => {return { type: numericProp, default: defVal };
};export const makeStringProp = <T>(defVal: T) => {return { type: String as unknown as PropType<T>, default: defVal };
};export const makeNumberProp = <T>(defVal: T) => {return { type: Number as unknown as PropType<T>, default: defVal };
};export const makeArrayProp = <T>(defVal: T[]) => {return { type: Array as PropType<T[]>, default: () => defVal };
};export const makeObjectProp = <T>(defVal: T) => {return { type: Object as PropType<T>, default: () => defVal };
};export const makeFuncProp = <T>(defVal: T) => {return { type: Function as PropType<T>, default: defVal };
};// 联和类型属性
export const makeUniteProp = <T, V>(type: T[], defVal: V) => {return { type, default: () => defVal };
};
import type { PropType, ExtractPropTypes } from "vue";import {makeArrayProp, makeRequiredProp} from "@/utils/props"export const props = {prop1: makeRequiredProp(String),prop2: makeArrayProp<string>(["a", "b", "c"]),prop3: makeArrayProp<Record<string, unknown>[]>([])
};export type Props = ExtractPropTypes<typeof props>;
参考资料💘
🍅因发布平台差异导致阅读体验不同,源文贴出:《『精』Vue 组件如何模块化抽离Props》
- 官方手册:
- Vue ExtractPropTypes
- Vue defineProps
- Vue Mixins
推荐博文🍗
- 《Vue3 如何在<script setup>里设置组件name属性》
- 《JavaScript 各声明var、let、const方式区别『详解』》
相关文章:

『精』Vue 组件如何模块化抽离Props
『精』Vue 组件如何模块化抽离Props 文章目录 『精』Vue 组件如何模块化抽离Props一、为什么要抽离Props二、选项式API方式抽离三、组合式API方式抽离3.1 TypeScript类型方式3.2 文件分离方式3.3 对文件分离方式优化 参考资料💘推荐博文🍗 一、为什么要抽…...
JavaScript字符串字面量详细解析与代码实例
JavaScript字符串字面量是一种表示字符串值的语法结构,通常用双引号或单引号括起来。 var str1 "Hello World!"; var str2 Hello World!;另外,如果需要在字符串中包含双引号或单引号,可以使用转义字符\来实现。 var str3 &quo…...

Android java Handler sendMessage使用Parcelable传递实例化对象,我这里传递Bitmap 图片数据
一、Bundle给我们提供了一个putParcelable(key,value)的方法。专门用于传递实例化对象。 二、我这里传递Bitmap 图片数据,实际使用可以成功传统图像数据。 发送:Bundle bundle new Bundle();bundle.putParcelable("bitmap",bitmap);msg.setD…...

CTF工具PDF隐写神器wbStego4open安装和详细使用方法
wbStego4open安装和详细使用方法 1.wbStego4open介绍:2.wbStego4open下载:3.wbStego4open原理图:4.wbStego4open使用教程:第一步:第二步:第三步:第四步:第五步: 5.wbSteg…...

docker镜像使用
一、查看docker版本 docker version docker默认安装目录 /var/lib/docker 目录文件如下: 二、查看下载的镜像 docker images 三、下载镜像 docker pull [OPTIONS] NAME[:TAG|DIGEST] option作用-a, --all-tags拉取所有 tagged 镜像–disable-content-trust…...

【Git】git的下载安装与使用
目录 目录 一.下载安装 官方下载 淘宝镜像下载 安装 二.创建本地仓库 三.git的基本操作命令 git status git add . git commit -m " " 四.gitee(码云)的使用 配置ssh公钥 编辑 查看公钥 gitee创建仓库 将本地仓库的文件上传到远程仓库…...
R语言中的函数27:polynom::polynomial(), deriv(),integral(),solve()多式处理函数
文章目录 介绍polynomial()用法参数实例多项式的加减乘除等运算实例 deriv()和integral()用法参数实例solve()参数实例 介绍 R语言中的polynom包可以实现对多项式的操作,例如:加、减、乘、除、微分、积分。使用的时候先用polynomial()函数定义一个多项式…...

基于STM32CubeMX和keil采用USART/UART实现非中断以及中断方式数据回环测试借助CH340以及XCOM
文章目录 前言1. 接口概述1.1 USART/UART接口1.2 串口通信参数1.3 波特率计算 2. 传输函数3. 回环测试3.1 上位机环境配置3.2 阻塞模式3.3 中断模式 4. STM32CubeMX配置4.1 时钟配置4.2 调试配置4.3 串口引脚配置4.4 工程配置 5. 测试效果6. 不借助上位机回环测试总结 前言 这…...

Spring cloud负载均衡 @LoadBalanced注解原理
接上一篇文章,案例代码也在上一篇文章的基础上。 在上一篇文章的案例中,我们创建了作为Eureka server的Eureka注册中心服务、作为Eureka client的userservice、orderservice。 orderservice引入RestTemplate,加入了LoadBalanced注解&#x…...
C#when关键字
在C#中,when关键字用于在模式匹配表达式中添加条件。它允许您在模式匹配的过程中指定额外的条件,以进一步过滤匹配的模式。当模式匹配和附加条件都为真时,相关的代码块将被执行。 以下是when关键字的详细解释以及示例说明: 语法…...
华为政企无线局域网产品集
产品类型产品型号产品说明 室内接入点AirEngine 5760-51AirEngine 5760-51是华为发布的支持Wi-Fi 6(802.11ax)标准的新一代室内AP,适合部署在企业办公、零售、制造等场景。 通过软件定义射频,能够在双频、三频模式灵活切换&a…...
解释 RESTful API
RESTful API是一种基于HTTP协议的API设计风格,它的核心思想是将每个资源(如用户、订单等)抽象成一个URI(统一资源标识符),通过HTTP协议定义的方法(如GET、POST、PUT、DELETE等)对资源…...

青翼科技-国产化ARM系列TES720D-KIT
板卡概述 TES720D-KIT是专门针对我司TES720D(基于复旦微FMQL20S400的全国产化ARM核心板)的一套开发套件,它包含1个TES720D核心板,加上一个TES720D-EXT扩展底板。 FMQL20S400是复旦微电子研制的全可编程融合芯片,在单…...
Tomcat为什么支持线程池?
Tomcat作为一个Java Servlet容器,支持线程池是因为它能够处理多个并发请求。这些请求可以是对Web应用程序的HTTP请求、Servlet的请求,或其他支持的协议。 支持线程池的主要原因包括: 并发处理能力: 提高性能: 使用线程…...

Mac安装VMware
去官网下载一下VMware Download VMware Fusion | VMware | SG 下载完成之后,打开直接闪退,参考这篇文章解决 解决macOS13安装Fusion13闪退的问题-CSDN博客 然后即可成功顺行...

项目部署文档
申请SSL证书 先申请,用免费的 下载证书 先将下载下来的保存起来 服务器安装JDK: 创建develop目录 mkdir /usr/local/develop/ 把JDK压缩包上传到/usr/local/develop/目录 解压安装包 并且将安装到指定目录 tar -zxvf /usr/local/develop/jdk-8u191-linux-x64.tar.gz -C /us…...
HTML+CSS阶段知识点梳理
目录 一、简单的网页结构 二、常用标签 三、列表 四、CSS引入方式 五、常用选择器 1、标签(元素)选择器 2、id选择器 3、class选择器 4、通配选择器 5、复合选择器 6、关系选择器 7、属性选择器 8、伪类选择器 9、a元素的伪类 10、伪元素…...

网易按照作者批量采集新闻资讯软件说明文档
大家好,我是淘小白~ 今天给大家介绍的爬虫软件是网易按照作者采集的软件 1、软件语言: Python 2、使用到的工具 Python selenium库、谷歌浏览器、谷歌浏览器驱动 3、文件说明: 4、配置文件说明: 5、环境配置 安装Python&am…...

SwiftUI 代码调试之都是“变心”惹的祸
0. 概览 这是一段非常简单的 SwiftUI 代码,我们将 Item 数组传递到子视图并在子视图中对其进行修改,修改的结果会立即在主视图中反映出来。 不幸的是,当我们修改 Item 名称时却发现不能连续输入:每次敲一个字符键盘都会立即收起并…...

u20.04安装slam库
git clone https://github.com/strasdat/Sophus.git // 下载的最新版是模板类的 git checkout a621ff // 切换为非模板类的历史版本 模板类Sophus的依赖库是Eigen(版本为3.3.X)和fmt,需提前安装好Eigen库和fmt库 git clone https://github.c…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...