Vue 3 + TypeScript 组件库开发实践
在现代前端开发中,Vue 3 结合 TypeScript 为组件库开发提供了强大的类型安全保障和开发体验。本文将分享我们在开发 Ghuo Design 组件库过程中的实践经验。
项目架构设计
目录结构
src/
├── components/ # 组件源码
│ ├── button/
│ ├── input/
│ └── ...
├── composables/ # 组合式函数
├── utils/ # 工具函数
├── types/ # 类型定义
└── styles/ # 样式文件TypeScript 配置
合理的 TypeScript 配置是项目成功的基础:
json
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"declaration": true,
"declarationMap": true
}
}组件开发最佳实践
1. 类型定义
为每个组件定义清晰的 Props 接口:
typescript
interface ButtonProps {
type?: 'primary' | 'secondary' | 'danger'
size?: 'small' | 'medium' | 'large'
disabled?: boolean
loading?: boolean
}2. 组合式 API 使用
充分利用 Vue 3 的 Composition API:
typescript
import { computed, ref } from 'vue'
export function useButton(props: ButtonProps) {
const isLoading = ref(false)
const buttonClass = computed(() => ({
[`ghuo-button--${props.type}`]: props.type,
[`ghuo-button--${props.size}`]: props.size,
'ghuo-button--disabled': props.disabled,
'ghuo-button--loading': isLoading.value
}))
return {
isLoading,
buttonClass
}
}3. 事件处理
正确定义和处理组件事件:
typescript
const emit = defineEmits<{
click: [event: MouseEvent]
change: [value: string]
}>()
const handleClick = (event: MouseEvent) => {
if (!props.disabled && !isLoading.value) {
emit('click', event)
}
}构建和发布
构建配置
使用 Vite 进行构建配置:
typescript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import dts from 'vite-plugin-dts'
export default defineConfig({
plugins: [
vue(),
dts({
insertTypesEntry: true
})
],
build: {
lib: {
entry: 'src/index.ts',
name: 'GhuoDesign',
fileName: 'ghuo-design'
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue'
}
}
}
}
})包管理
合理配置 package.json:
json
{
"name": "@ghuo/design",
"version": "1.0.0",
"main": "dist/ghuo-design.umd.js",
"module": "dist/ghuo-design.es.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"peerDependencies": {
"vue": "^3.0.0"
}
}测试策略
单元测试
使用 Vitest 进行单元测试:
typescript
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import Button from '../Button.vue'
describe('Button', () => {
it('renders correctly', () => {
const wrapper = mount(Button, {
props: {
type: 'primary'
},
slots: {
default: 'Click me'
}
})
expect(wrapper.text()).toBe('Click me')
expect(wrapper.classes()).toContain('ghuo-button--primary')
})
})类型测试
确保类型定义的正确性:
typescript
import type { ButtonProps } from '../types'
// 类型测试
const validProps: ButtonProps = {
type: 'primary',
size: 'large',
disabled: false
}
// @ts-expect-error - 应该报错
const invalidProps: ButtonProps = {
type: 'invalid',
size: 'huge'
}性能优化
1. 按需加载
支持按需导入组件:
typescript
// 全量导入
import GhuoDesign from '@ghuo/design'
// 按需导入
import { Button, Input } from '@ghuo/design'2. Tree Shaking
确保构建产物支持 Tree Shaking:
typescript
// src/index.ts
export { default as Button } from './components/button'
export { default as Input } from './components/input'
export type * from './types'文档和示例
组件文档
为每个组件编写详细的文档:
markdown
## Button 按钮
按钮用于开始一个即时操作。
### 基础用法
最简单的用法。
### API
#### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| type | 按钮类型 | `primary \| secondary \| danger` | `primary` |
| size | 按钮大小 | `small \| medium \| large` | `medium` |在线示例
提供可交互的在线示例:
vue
<template>
<div class="demo">
<ghuo-button
:type="type"
:size="size"
@click="handleClick"
>
{{ text }}
</ghuo-button>
</div>
</template>总结
Vue 3 + TypeScript 的组合为组件库开发提供了:
- 类型安全:编译时错误检查
- 更好的 IDE 支持:智能提示和重构
- 可维护性:清晰的接口定义
- 开发体验:强大的工具链支持
通过合理的架构设计、规范的开发流程和完善的测试策略,我们可以构建出高质量的 Vue 3 组件库。
发布于 2024年1月15日