1. 组件目录结构
将所有的组件放在统一的components
目录中,并按功能进行分类。例如:
scss
src/
└── components/
├── common/ // 公共组件
│ ├── Button.vue
│ ├── Modal.vue
│ └── Icon.vue
├── user/ // 用户模块相关组件
│ ├── UserProfile.vue
│ └── UserList.vue
├── product/ // 产品模块相关组件
│ ├── ProductCard.vue
│ └── ProductList.vue
- 建议:每个文件夹下组件数量不宜过多,保证分类清晰。
- 分层级结构 :根据组件的作用范围进行分类,如
common
存放通用组件,feature
存放特定功能模块的组件。
2. 组件命名
-
组件文件名 :使用大驼峰命名法(PascalCase),与组件名保持一致,例如
UserProfile.vue
、ProductCard.vue
。 -
组件名称 :组件的
name
字段使用大驼峰命名法,保持与文件名一致,方便调试和排查。 -
命名建议:
- 使用名词或名词短语,表示组件的功能或内容。
- 对于复用性高的组件,如
Button
、Input
,应保持名称简洁明确。 - 对于特定模块的组件,可以在名称中体现模块名,例如
UserList
、ProductCard
等。
3. 组件类型划分
根据组件的功能和重用性,划分为以下几类:
-
基础组件(Base Components):
- 这些组件通常是没有业务逻辑的纯UI组件,如
Button
、Input
、Icon
等。 - 命名通常以
Base
开头,例如BaseButton.vue
、BaseInput.vue
。
- 这些组件通常是没有业务逻辑的纯UI组件,如
-
业务组件(Business Components):
- 这些组件与业务逻辑相关,包含特定模块功能,如
UserProfile.vue
、ProductCard.vue
等。
- 这些组件与业务逻辑相关,包含特定模块功能,如
-
页面级组件(Page Components):
- 页面级别的组件用于构建整个页面,通常在
pages
目录下管理,并通过路由直接渲染。
- 页面级别的组件用于构建整个页面,通常在
4. 组件内结构规范
组件内代码顺序
-
组件内部代码顺序应保持一致,建议如下顺序:
name
:组件名称,方便调试和查错。props
:接收的外部属性。data
:组件内部的状态数据。computed
:计算属性,派生数据。methods
:组件的业务逻辑方法。watch
:监控属性变化。lifecycle hooks
:生命周期钩子函数。
-
示例:
js<script> export default { name: 'UserProfile', props: { userId: { type: String, required: true } }, data() { return { userProfile: null }; }, computed: { formattedName() { return this.userProfile ? `${this.userProfile.firstName} ${this.userProfile.lastName}` : ''; } }, methods: { async fetchUserProfile() { // 业务逻辑 } }, mounted() { this.fetchUserProfile(); } }; </script>
Props 规范
-
类型定义 :在
props
中定义时,必须明确类型,使用type
,并添加required
字段来说明该prop
是否必需。 -
默认值 :使用
default
字段提供默认值。 -
规范示例:
jsprops: { userId: { type: String, required: true }, isActive: { type: Boolean, default: false }, options: { type: Array, default: () => [] } }
5. 组件通信
父子组件通信(Props & Emit)
-
Props :父组件通过
props
传递数据到子组件,确保父组件控制数据流。 -
Emit :子组件通过
$emit
通知父组件事件。 -
示例:
-
父组件传递
prop
s:js<UserProfile :userId="userId" @update="handleUpdate" />
-
子组件
emit
事件:jsthis.$emit('update', updatedData);
-
非父子组件通信(EventBus 或 Vuex)
- EventBus:使用事件总线进行跨组件的通信,但建议在较大项目中使用Vuex来管理全局状态。
- Vuex:使用状态管理工具Vuex进行全局状态的管理和数据传递。
6. 组件样式规范
局部样式作用域
-
使用
<style scoped>
来确保组件样式局部化,避免样式污染。 -
示例:
html<style scoped> .user-profile { font-size: 14px; } </style>
样式命名(BEM命名法)
-
推荐使用BEM(Block Element Modifier)命名法管理样式。
-
示例:
html<template> <div class="user-profile"> <div class="user-profile__header">Header</div> <div class="user-profile__body">Body</div> <div class="user-profile__footer user-profile__footer--active">Footer</div> </div> </template>
Block :
user-profile
Element :
user-profile__header
,user-profile__body
Modifier :
user-profile__footer--active
7. 组件重用
公共组件
- 创建公共组件库 :提取项目中复用率高的组件,形成独立的公共组件库,例如
Button.vue
、Modal.vue
等。 - 按需加载:通过动态加载或按需引入的方式减少组件加载时的性能开销。
复用方法与逻辑(Mixin)
-
Mixin :对于多个组件之间共享的逻辑,可以使用
mixin
,实现代码重用。 -
示例:
jsexport const userMixin = { data() { return { userData: {} }; }, methods: { fetchUserData() { // 复用的逻辑 } } };
在组件中使用:
jsimport { userMixin } from '@/mixins/userMixin'; export default { mixins: [userMixin], mounted() { this.fetchUserData(); } };
8. 组件性能优化
-
异步组件 :对于非关键路径的组件,可以使用
Vue
的异步组件加载功能进行按需加载,减少初始包体积。jsconst AsyncComponent = () => import('./components/AsyncComponent.vue');
-
懒加载:图片等资源可以使用懒加载技术,减少页面的初始加载时间。
-
避免不必要的重渲染 :使用
key
值优化组件更新,避免无意义的重绘。
9. 组件测试
-
单元测试: 对每个组件编写单元测试,确保其功能和界面表现正确。使用
Jest
或Mocha
进行测试。测试内容 :组件的渲染、
props
传递、事件触发等。jsimport { shallowMount } from '@vue/test-utils'; import UserProfile from '@/components/UserProfile.vue'; test('should render user profile', () => { const wrapper = shallowMount(UserProfile, { propsData: { userId: '123' } }); expect(wrapper.find('.user-profile').exists()).toBe(true); });
通过严格遵循这些组件化规范,能够确保代码的模块化、可维护性和重用性,减少项目开发中的复杂性并提升代码质量。