菏泽市城乡和建设局网站,广东新闻联播2020,西安住房建设局网站,免费收录链接网『精』Vue 组件如何模块化抽离Props 文章目录 『精』Vue 组件如何模块化抽离Props一、为什么要抽离Props二、选项式API方式抽离三、组合式API方式抽离3.1 TypeScript类型方式3.2 文件分离方式3.3 对文件分离方式优化 参考资料#x1f498;推荐博文#x1f357; 一、为什么要抽…
『精』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 PropTypestring[],default: [a, b, c]},prop3: {type: Array as PropTypeRecordstring, unknown[],defalue: []}}
};
script langtsimport 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?: Recordstring, unknown[];
}export const propsDefault {prop1: 默认值,prop2: () [a, b, c]
};
templatediv{{ $props.prop1 }}/divdiv{{ $props.prop2 }}/div
/templatescript langts setupimport { type Props, propsDefault } from ./props;const $props withDefaults(definePropsProps(), propsDefault);/script3.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 PropTypestring[],default: [a, b, c]},prop3: {type: Array as PropTypeRecordstring, unknown[],defalue: []}
};
templatediv{{ $props.prop1 }}/divdiv{{ $props.prop2 }}/div
/templatescript langts setupconst $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 PropTypestring[],default: [a, b, c]},prop3: {type: Array as PropTypeRecordstring, unknown[],defalue: []}
};// 导出 Props 类型
export type Props ExtractPropTypestypeof props;
其实 ElementUI 的源码也是这么去做的以 el-empty 组件为例源码中对于属性的分离是这么写的。
3.3 对文件分离方式优化
从优化的角度上看Vue 的Props声明方式都是一样的同样的代码写多次显得有些冗余那不妨将这些 Props 声明再次优化一下编写一个公共的 Props 辅助工具进行声明。
use strict;
/*** 组件属性辅助* 能够使用更少的代码编写有助于减少包体积*/
import type { PropType } from vue;export const unknownProp null as unknown as PropTypeunknown;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 PropTypeT, default: defVal };
};export const makeNumberProp T(defVal: T) {return { type: Number as unknown as PropTypeT, default: defVal };
};export const makeArrayProp T(defVal: T[]) {return { type: Array as PropTypeT[], default: () defVal };
};export const makeObjectProp T(defVal: T) {return { type: Object as PropTypeT, default: () defVal };
};export const makeFuncProp T(defVal: T) {return { type: Function as PropTypeT, 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/propsexport const props {prop1: makeRequiredProp(String),prop2: makeArrayPropstring([a, b, c]),prop3: makeArrayPropRecordstring, unknown[]([])
};export type Props ExtractPropTypestypeof props; 参考资料
因发布平台差异导致阅读体验不同源文贴出《『精』Vue 组件如何模块化抽离Props》
官方手册 Vue ExtractPropTypesVue definePropsVue Mixins 推荐博文
《Vue3 如何在script setup里设置组件name属性》《JavaScript 各声明var、let、const方式区别『详解』》