从基础的组件看看Element-plus实现组建的基本流程
目录 packages\components\icon

因为我们分析源码的目的是学习如何构建组件库已经封装复用性强的组件所以跳过.tsx
文件从src
目录开始看。
icon.ts
js
import { buildProps, definePropType } from '@element-plus/utils'
buildProps,definePropType(export const definePropType = <T>(val: any): PropType<T> => val
)。definePropType定义了泛型的props类型,buildProps是对 element 组件开发过程中,大家编码时的 Props 的设置,进行了统一格式化。

js
import type { ExtractPropTypes } from 'vue'
import type Icon from './icon.vue'
使用 import 的话,TypeScript 是无法判断你是想导出类型还是一个 JavaScript 的方法或者变量。
所以 TypeScript 提供了 import type or export type,用来明确表示我引入/导出的是一个类型,而不是一个变量或者方法。
定义组件需要的参数
js
export const iconProps = buildProps({
/**
* @description SVG icon size, size x size
*/
size: {
type: definePropType<number | string>([Number, String]),
},
/**
* @description SVG tag's fill attribute
*/
color: {
type: String,
},
} as const)
as const 则可以快速将一个对象变成只读类型,常量断言可以把一个值标记为一个不可篡改的常量,从而让 TS 以最严格的策略来进行类型推断。
js
export type IconProps = ExtractPropTypes<typeof iconProps>
vue3 string构造函数 在TS类型中是他的构造函数类型:StringConstructor
并不是我们想要的,我们希望string构造函数返回的是字符串类型string. vue3提供了prop类型申明ExtractPropTypes
用于接收一个类型用yu把接收的prop类型返回出来;也可以把构造函数类型转换为对应的类型如:StringConstructor 转换成 string。
js
export type IconInstance = InstanceType<typeof Icon> & unknown
返回SFC 实例类型,InstanceType 函数:该函数返回(构造) 由某个构造函数构造出来的实例类型组成的类型
icon/index.ts
js
import { withInstall } from '@element-plus/utils'
import Icon from './src/icon.vue'
import type { SFCWithInstall } from '@element-plus/utils'
//组件类型引入
export const ElIcon: SFCWithInstall<typeof Icon> = withInstall(Icon)
// 通过 withInstall 方法给 Icon 添加了一个 install 方法
export default ElIcon
// 导出 iCON 组件
export * from './src/icon'
至此,对icon组件的分析就结束了。涉及的withInstall
是组件库注册的公共方法。
具体目录是packages\utils\vue\install.ts
js
export const withInstall = <T, E extends Record<string, any>>(
main: T,
extra?: E
) => {
;(main as SFCWithInstall<T>).install = (app): void => {
for (const comp of [main, ...Object.values(extra ?? {})]) {
app.component(comp.name, comp)
}
}
if (extra) {
for (const [key, comp] of Object.entries(extra)) {
;(main as any)[key] = comp
}
}
return main as SFCWithInstall<T> & E
}
// 组件注册的公共方法
传递两个参数,main类型为泛型T,extra是一个对象,通过Object.values 将 extra 中的属性值提取为一个数组,并进行遍历进行 组件的注册.
如果extra不为空则通过 迭代器遍历 Object.entries 转换后的 二维数组, 将extra所有属性和值 挂载到 main 对象下
SFCWithInstall 通过泛型 将最后返回的 main 的类型 定义为 T & Plugin & E的交叉类型,为并且关系