从最简单的 icon组件开始了解Element-Plus 源码

从基础的组件看看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的交叉类型,为并且关系
相关推荐
会飞的架狗师1 天前
【MySQL体系】第8篇:MySQL集群架构技术详解
数据库·mysql·架构
周杰伦_Jay1 天前
【实战|旅游知识问答RAG系统全链路解析】从配置到落地(附真实日志数据)
大数据·人工智能·分布式·机器学习·架构·旅游·1024程序员节
IT小番茄1 天前
政策风口下的万亿市场:"十五五"一网统飞如何引爆无人机AI巡检革命?
架构
IT小番茄1 天前
双碳目标下的智慧水务革命:IoT物联网平台如何重塑污水处理未来?
架构
Java 码农1 天前
mysql8.4.6 LTS 主从架构搭建
mysql·adb·架构
麦麦大数据1 天前
F038 vue+flask 微博舆情热搜情感分析大数据分析系统|前后端分离架构
vue.js·架构·flask·情感分析·微博·舆情分析
明仔的阳光午后1 天前
React 入门 01:快速写一个React的HelloWorld项目
前端·javascript·react.js·前端框架·reactjs·react
sorryhc1 天前
Webpack中的插件流程是怎么实现的?
前端·webpack·架构
gfdgd xi2 天前
GXDE For deepin 25:deepin25 能用上 GXDE 了!
linux·运维·python·ubuntu·架构·bug·deepin
光影少年2 天前
React Navite 第二章
前端·react native·react.js·前端框架