当前位置: 首页 > news >正文

组件库设计与开发:打造可复用的组件生态

组件库设计与开发:打造可复用的组件生态

大家好,我是蔓蔓。在大厂工作时,我主导开发过团队内部的组件库,大大提升了开发效率。今天我来和大家分享组件库设计与开发的完整方案。

组件库架构设计

目录结构

my-ui-library/ ├── packages/ │ ├── button/ │ │ ├── src/ │ │ │ └── Button.vue │ │ ├── index.js │ │ └── package.json │ ├── input/ │ └── ... ├── docs/ │ └── components/ ├── scripts/ │ └── build.js ├── jest.config.js └── package.json

核心原则

// 1. 单一职责原则// 一个组件只做一件事// 2. 可组合性// 组件可以互相组合使用// 3. 可配置性// 通过props配置,减少magic// 4. 良好的默认值// 开箱即用,减少配置// 5. 完整的文档和示例// 降低使用门槛

基础组件开发

按钮组件

<template> <button :class="buttonClasses" :disabled="disabled || loading" @click="handleClick" > <span v-if="loading" class="loading">loading...</span> <span v-else> <slot></slot> </span> </button> </template> <script> export default { name: 'Button', props: { type: { type: String, default: 'default', validator: value => ['default', 'primary', 'success', 'warning', 'danger'].includes(value) }, size: { type: String, default: 'medium', validator: value => ['small', 'medium', 'large'].includes(value) }, disabled: { type: Boolean, default: false }, loading: { type: Boolean, default: false } }, computed: { buttonClasses() { return [ 'my-button', `my-button--${this.type}`, `my-button--${this.size}`, { 'is-disabled': this.disabled, 'is-loading': this.loading } ] } }, methods: { handleClick(event) { if (!this.disabled && !this.loading) { this.$emit('click', event); } } } } </script> <style scoped> .my-button { display: inline-flex; align-items: center; justify-content: center; border: 1px solid #ddd; border-radius: 4px; padding: 8px 16px; font-size: 14px; cursor: pointer; transition: all 0.3s; } .my-button--primary { background-color: #1890ff; color: white; border-color: #1890ff; } .my-button--success { background-color: #52c41a; color: white; border-color: #52c41a; } .my-button--small { padding: 4px 12px; font-size: 12px; } .my-button--large { padding: 12px 20px; font-size: 16px; } .is-disabled { opacity: 0.6; cursor: not-allowed; } </style>

表单组件

<template> <div class="my-input-wrapper"> <label v-if="label" :class="labelClass"> {{ label }} <span v-if="required" class="required">*</span> </label> <input ref="inputRef" v-model="innerValue" :class="inputClasses" :placeholder="placeholder" :disabled="disabled" :type="type" @focus="handleFocus" @blur="handleBlur" @input="handleInput" /> <div v-if="errorMessage" class="error-message">{{ errorMessage }}</div> </div> </template> <script> export default { name: 'Input', inheritAttrs: false, props: { modelValue: [String, Number], label: String, type: { type: String, default: 'text' }, placeholder: String, disabled: Boolean, required: Boolean, rules: { type: Array, default: () => [] }, clearable: Boolean }, data() { return { innerValue: this.modelValue, isFocused: false, errorMessage: '' } }, watch: { modelValue(val) { this.innerValue = val; } }, computed: { inputClasses() { return [ 'my-input', { 'is-focused': this.isFocused, 'is-error': this.errorMessage } ] }, labelClass() { return ['my-input__label', { 'is-required': this.required }] } }, methods: { handleFocus() { this.isFocused = true; this.$emit('focus'); }, handleBlur() { this.isFocused = false; this.$emit('blur'); this.validate(); }, handleInput(event) { this.$emit('update:modelValue', event.target.value); this.$emit('input', event); }, validate() { for (const rule of this.rules) { if (rule.required && !this.innerValue) { this.errorMessage = rule.message || '此字段必填'; return false; } if (rule.pattern && !rule.pattern.test(this.innerValue)) { this.errorMessage = rule.message || '格式不正确'; return false; } } this.errorMessage = ''; return true; }, clear() { this.innerValue = ''; this.$emit('update:modelValue', ''); } } } </script>

组件库构建

使用Vite构建

// vite.config.jsimport{defineConfig}from'vite';importvuefrom'@vitejs/plugin-vue';import{resolve}from'path';exportdefaultdefineConfig({plugins:[vue()],build:{lib:{entry:resolve(__dirname,'packages/index.js'),name:'MyUI',formats:['es','umd']},rollupOptions:{external:['vue'],output:{globals:{vue:'Vue'}}}}});

package.json

{"name":"my-ui-library","version":"1.0.0","description":"A Vue 3 component library","main":"dist/my-ui-library.umd.js","module":"dist/my-ui-library.es.js","types":"dist/index.d.ts","files":["dist"],"scripts":{"build":"vite build","test":"jest","lint":"eslint packages/"},"peerDependencies":{"vue":"^3.0.0"},"devDependencies":{"@vitejs/plugin-vue":"^4.0.0","vite":"^4.0.0","jest":"^29.0.0"}}

组件库文档

使用VitePress

# Button 按钮 ## 基础用法 <Button type="primary">主要按钮</Button> <Button type="success">成功按钮</Button> ```vue <Button type="primary">主要按钮</Button>

API

Props

参数说明类型默认值
type类型string‘default’
size尺寸string‘medium’

Events

事件名说明回调参数
click点击event
## 总结 一个好的组件库能显著提升团队开发效率。通过合理的架构设计,注重组件的可复用性和可维护性,提供完善的文档和示例,你的组件库会成为团队的宝贵资产。 技术应当有温度,好的组件库能让开发者更专注于业务逻辑。
http://www.jsqmd.com/news/798237/

相关文章:

  • 当Agent接入物联网:智能家居的终极形态畅想
  • 专业日志分析工具深度解析:LogExpert提升工作效率的7大实战技巧
  • 如何用3分钟永久保存你珍爱的B站视频?解密m4s-converter的智能转换方案
  • AD19原理图编译总报off grid pin警告?手把手教你从库源头搞定封装与栅格对齐
  • 华为光猫配置文件解密实战:网络工程师的高效工具箱
  • 项目-轻客管家1-环境准备
  • 十堰改灯首选|千言改灯(前沿改灯):2026最新十堰改灯市场分析十堰改灯首推首选五星级靠谱口碑门店 - Reaihenh
  • 洛谷 P1305:新二叉树 ← DFS
  • 抖音视频怎么去水印?手机电脑都能用的工具对比,2026 免费方案实测 - 科技热点发布
  • 从业者必看:医药资质认证服务核心知识梳理
  • AI东风起,深圳存储与液冷企业市值狂飙,催生一批百亿富豪
  • 工业AI和大模型是一回事吗?拆解制造业场景里的关键技术逻辑
  • 浙江省人民政府于2025年1月26日公布新版《浙江省重点保护陆生野生动物名录》
  • 构建高效团队协作平台:从作战室思维到工程化实践
  • 2026届最火的十大降AI率方案解析与推荐
  • C语言打印三角形别再只会用*了!用字母、数字、符号玩出新花样(附完整代码)
  • SiC晶圆划裂技术:原理、优化与量产挑战
  • Zynq-7000 PL端I2C IP核驱动光模块,设备树配置避坑指南(附完整DTS代码)
  • 2026去水印小程序哪个好用?4款微信小程序排行榜实测对比,新手秒上手 - 科技热点发布
  • Redis哨兵模式详解
  • 完整资源下载|MATLAB|Python代码|Simulink等资源下载|MATLAB|抽水蓄能电站系统的最优竞价策略研究
  • 在DMXAPI上遇见扣子:一次偶然,才开启的AI之旅
  • 从按键开机到I2C隔离:手把手拆解一个智能硬件项目里的MOS管实战配置
  • 从基础到进阶:掌握Matlab mean函数的全维度数据均值计算
  • 3分钟完成Android Studio完全汉化:官方修改版中文语言包终极指南
  • 【最新 v2.7.1 版本】 OpenClaw 2.7.1 极简部署方法及安装包
  • 戴尔OptiPlex安装Ubuntu:从ACPI报错到网卡驱动的完整排障指南
  • 42岁程序员8个月求职记:AI时代,经验贬值?3条转型路径助你逆袭!
  • 2026免费去水印视频软件怎么选?排行榜与最新推荐指南 - 科技热点发布
  • 程力专用汽车股份有限公司官网:全品类车型与服务一站式查询 - 速递信息