Skip to content

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 的组合为组件库开发提供了:

  1. 类型安全:编译时错误检查
  2. 更好的 IDE 支持:智能提示和重构
  3. 可维护性:清晰的接口定义
  4. 开发体验:强大的工具链支持

通过合理的架构设计、规范的开发流程和完善的测试策略,我们可以构建出高质量的 Vue 3 组件库。


发布于 2024年1月15日

Released under the MIT License.