各位靓仔靓女,今天咱们来聊聊如何在多团队的 Vue 项目里,搞一套通用的组件库规范,再用 Storybook 把组件文档管起来。这事儿说难不难,说简单也不简单,关键是要捋顺思路,定好规矩。
一、组件库规范:咱们先定个“家规”
在多团队协作中,没有规矩不成方圆。组件库规范就好比咱们的“家规”,它能保证大家写出来的组件风格一致,易于维护,减少踩坑。
-
命名规范:起个好名字很重要
组件的命名要清晰、简洁、语义化。推荐使用 PascalCase 命名法(首字母大写),例如
MyButton
、UserProfile
。- 组件文件夹命名: 以组件名为准,例如
components/MyButton/
。 - 组件文件名: 与组件名相同,例如
MyButton.vue
。 - Props 命名: 使用 camelCase 命名法(小驼峰),例如
buttonText
、isDisabled
。 - Events 命名: 使用 camelCase 命名法,例如
onClick
、onInputChange
。
// MyButton.vue <template> <button :disabled="isDisabled" @click="onClick">{{ buttonText }}</button> </template> <script> export default { name: 'MyButton', props: { buttonText: { type: String, default: 'Click Me' }, isDisabled: { type: Boolean, default: false } }, emits: ['click'], methods: { onClick() { this.$emit('click'); } } }; </script>
- 组件文件夹命名: 以组件名为准,例如
-
目录结构:家里得收拾利索
一个组件的目录结构应该清晰明了,方便查找和维护。推荐结构如下:
components/ MyButton/ MyButton.vue // 组件文件 MyButton.stories.js // Storybook 文件 index.js // 组件导出 style.scss // 组件样式(可选)
MyButton.vue
:组件的核心代码。MyButton.stories.js
:Storybook 的故事文件,用于展示组件的不同状态和用法。index.js
:用于统一导出组件,方便其他模块引入。
// index.js import MyButton from './MyButton.vue'; export default MyButton;
-
Props 定义:说清楚组件要什么
Props 是组件接收数据的入口,要明确定义 Props 的类型、是否必填、默认值等。使用
type
、required
、default
等属性进行约束。// MyButton.vue <script> export default { name: 'MyButton', props: { buttonText: { type: String, default: 'Click Me', description: '按钮显示的文本' // 描述 Props 的作用 }, isDisabled: { type: Boolean, default: false, description: '是否禁用按钮' }, size: { type: String, default: 'medium', validator: function (value) { // 这个值必须匹配下列字符串中的一个 return ['small', 'medium', 'large'].indexOf(value) !== -1 }, description: '按钮尺寸,可选值:small、medium、large' } } }; </script>
type
:指定 Props 的数据类型,常用的有String
、Number
、Boolean
、Array
、Object
、Function
、Symbol
。required
:指定 Props 是否必填。default
:指定 Props 的默认值。description
:描述 Props 的作用,方便阅读和理解。validator
: 自定义校验props的值
-
Events 定义:组件能干啥也要说清楚
Events 是组件向外发送消息的通道,要明确定义 Events 的名称和传递的数据。使用
$emit
触发事件。// MyButton.vue <script> export default { name: 'MyButton', emits: ['click', 'custom-event'], methods: { onClick() { this.$emit('click'); this.$emit('custom-event', { message: 'Button clicked!' }); } } }; </script>
emits
:声明组件会触发的事件,可以是一个数组或一个对象。如果是对象,可以定义事件的参数校验。
-
样式规范:穿衣打扮要统一
样式方面,推荐使用 CSS Modules 或 scoped CSS,避免样式冲突。如果使用 CSS Modules,需要配置 Webpack。
// MyButton.vue <template> <button :class="$style.button" :disabled="isDisabled" @click="onClick">{{ buttonText }}</button> </template> <script> export default { name: 'MyButton' }; </script> <style module lang="scss"> .button { background-color: #4CAF50; border: none; color: white; padding: 10px 20px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; cursor: pointer; border-radius: 4px; &:disabled { background-color: #cccccc; cursor: not-allowed; } } </style>
-
代码注释:好记性不如烂笔头
重要的代码逻辑要添加注释,方便自己和他人阅读。
// MyButton.vue <script> export default { name: 'MyButton', methods: { /** * 点击按钮的处理函数 * @param {Event} event 点击事件对象 */ onClick(event) { // 阻止事件冒泡 event.stopPropagation(); this.$emit('click'); } } }; </script>
-
可访问性(Accessibility):关爱弱势群体
组件要考虑可访问性,例如使用
aria-label
属性,为屏幕阅读器提供信息。// MyButton.vue <template> <button :aria-label="buttonText" :disabled="isDisabled" @click="onClick">{{ buttonText }}</button> </template>
-
国际化(i18n):走向世界,拥抱多元
组件要支持国际化,方便在不同语言环境下使用。可以使用 Vue I18n 等库来实现。
-
测试:质量是生命线
组件要编写单元测试,保证组件的质量。可以使用 Jest、Mocha 等测试框架。
// MyButton.spec.js import { shallowMount } from '@vue/test-utils'; import MyButton from './MyButton.vue'; describe('MyButton.vue', () => { it('renders button text correctly', () => { const wrapper = shallowMount(MyButton, { propsData: { buttonText: 'Test Button' } }); expect(wrapper.text()).toContain('Test Button'); }); it('emits click event when clicked', async () => { const wrapper = shallowMount(MyButton); await wrapper.find('button').trigger('click'); expect(wrapper.emitted('click')).toBeTruthy(); }); });
二、Storybook:组件的“秀场”
Storybook 是一个 UI 组件开发环境,可以用来展示、测试和文档化 Vue 组件。
-
安装 Storybook
在 Vue 项目中安装 Storybook:
npx sb init --type vue3
-
编写 Storybook 故事
在组件目录中创建
MyButton.stories.js
文件,编写故事:// MyButton.stories.js import MyButton from './MyButton.vue'; export default { title: 'Components/MyButton', component: MyButton, argTypes: { buttonText: { control: 'text', description: '按钮显示的文本' }, isDisabled: { control: 'boolean', description: '是否禁用按钮' }, onClick: { action: 'clicked', description: '点击事件' }, size: { control: { type: 'select' }, options: ['small', 'medium', 'large'], description: '按钮尺寸,可选值:small、medium、large' } }, }; const Template = (args) => ({ components: { MyButton }, setup() { return { args }; }, template: '<MyButton v-bind="args" />', }); export const Primary = Template.bind({}); Primary.args = { buttonText: 'Primary Button', }; export const Disabled = Template.bind({}); Disabled.args = { buttonText: 'Disabled Button', isDisabled: true, }; export const Small = Template.bind({}); Small.args = { buttonText: 'Small Button', size: 'small', }
title
:指定故事在 Storybook 中的分类。component
:指定要展示的组件。argTypes
:定义组件的 Props,可以控制 Props 的类型、控件类型、描述等。Template
:定义故事的模板,用于渲染组件。Primary
、Disabled
:定义不同的故事,展示组件的不同状态和用法。args
:为故事设置 Props 的值。action
:可以展示事件的触发情况。
-
运行 Storybook
运行 Storybook:
npm run storybook
Storybook 会在浏览器中打开,展示组件的故事。
-
Storybook 的高级用法
- 控制 Props: 使用
argTypes
可以控制 Props 的类型、控件类型、描述等。 - 展示事件: 使用
action
可以展示事件的触发情况。 - 编写文档: 使用 Markdown 编写组件的文档,包括组件的用法、注意事项等。
- 添加 Addons: Storybook 有很多 Addons,可以扩展 Storybook 的功能,例如添加主题切换、国际化等。
- 集成测试: 可以将 Storybook 与测试框架集成,进行视觉回归测试。
- 控制 Props: 使用
三、组件库发布与使用
-
发布组件库
将组件库发布到 npm 或私有仓库,方便其他项目使用。
-
配置
package.json
:{ "name": "@your-org/my-component-library", "version": "1.0.0", "description": "A Vue component library", "main": "dist/my-component-library.umd.js", "module": "dist/my-component-library.es.js", "exports": { ".": { "import": "./dist/my-component-library.es.js", "require": "./dist/my-component-library.umd.js" } }, "files": [ "dist" ], "scripts": { "build": "vue-cli-service build --target lib --name my-component-library src/index.js" }, "peerDependencies": { "vue": "^3.0.0" } }
name
:组件库的名称,推荐使用@组织名/组件库名
的格式。version
:组件库的版本号。main
:CommonJS 规范的入口文件。module
:ES Module 规范的入口文件。exports
:定义不同环境下的入口文件。files
:指定要发布的文件。scripts
:定义构建命令。peerDependencies
:指定组件库依赖的 Vue 版本。
-
构建组件库:
npm run build
-
发布组件库:
npm publish
-
-
使用组件库
在其他 Vue 项目中安装组件库:
npm install @your-org/my-component-library
在 Vue 组件中引入并使用组件:
<template> <MyButton buttonText="Click Me" @click="handleClick" /> </template> <script> import MyButton from '@your-org/my-component-library'; export default { components: { MyButton }, methods: { handleClick() { alert('Button clicked!'); } } }; </script>
四、多团队协作的注意事项
- 统一开发规范: 制定统一的开发规范,包括代码风格、命名规范、目录结构等。
- 代码审查: 实施代码审查制度,保证代码质量。
- 版本控制: 使用 Git 等版本控制工具,管理代码变更。
- 持续集成: 使用 Jenkins、GitLab CI 等持续集成工具,自动化构建、测试和部署。
- 沟通协作: 建立良好的沟通协作机制,例如定期召开会议、使用 Slack 等即时通讯工具。
- 组件库维护: 指定专门的团队或人员负责组件库的维护,及时修复 Bug、添加新功能。
五、总结
组件库规范和 Storybook 是多团队协作 Vue 项目的利器。通过制定统一的规范,可以保证组件的质量和一致性;通过 Storybook,可以方便地展示、测试和文档化组件。希望今天的分享对大家有所帮助!
表格总结关键点
规范领域 | 关键点 | 说明 |
---|---|---|
命名规范 | PascalCase (组件), camelCase (props, events) | 统一的命名风格提高代码可读性. |
目录结构 | 组件名/ 组件名.vue, 组件名.stories.js, index.js, style.scss | 清晰的目录结构方便查找和维护. |
Props | 类型, 必填, 默认值, 描述, 校验 | 明确 Props 的定义,减少使用错误. |
Events | 名称, 传递数据 | 明确 Events 的定义,方便其他组件使用. |
样式规范 | CSS Modules, scoped CSS | 避免样式冲突. |
代码注释 | 必要的注释 | 方便代码阅读和理解. |
可访问性 | aria-label 等属性 | 关爱弱势群体,提高用户体验. |
国际化 | 支持 i18n | 方便在不同语言环境下使用. |
测试 | 单元测试 | 保证组件质量. |
Storybook | 展示组件, 测试组件, 文档化组件 | 提供组件的 "秀场",方便开发和使用. |
多团队协作 | 统一开发规范, 代码审查, 版本控制, 持续集成, 沟通协作, 组件库维护 | 保证项目顺利进行. |
希望这些信息对您有所帮助! 如果您有任何其他问题,请随时提出。