1. Vue3项目结构全景解析
刚接手一个Vue3项目时,我常常会对着src目录里十几个文件夹发懵——这些文件到底该怎么组织才合理?经过三年多的Vue3实战,我总结出一套经过大型项目验证的目录结构方案。与Vue2时代不同,Vue3的Composition API和TypeScript深度集成带来了全新的代码组织思路。
现代Vue3项目的典型结构是这样的:
code复制src/
├── assets/ # 静态资源
├── components/ # 公共组件
│ ├── ui/ # 基础UI组件
│ └── business/ # 业务组件
├── composables/ # 组合式函数
├── stores/ # 状态管理
├── router/ # 路由配置
├── utils/ # 工具函数
├── views/ # 页面级组件
├── types/ # TS类型定义
└── main.ts # 应用入口
这种结构最显著的特点是按功能而非文件类型划分。在Vue2时代常见的按components/views分目录的方式,现在被更细粒度的职责划分取代。比如composables目录专门存放use开头的组合式函数,stores目录集中管理Pinia状态模块。
关键经验:避免在components目录下直接放置大量平级组件。建议至少划分ui(基础组件)和business(业务组件)两个子目录,当组件超过20个时再按业务域细分。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 组件化架构的进化实践
2.1 原子设计理论的落地
在电商项目中,我采用Brad Frost的原子设计理论重构了组件体系:
code复制components/
├── atoms/ # 按钮/输入框等基础原子
│ ├── AppButton.vue
│ └── AppInput.vue
├── molecules/ # 表单组合等分子组件
│ ├── SearchForm.vue
│ └── FilterPanel.vue
├── organisms/ # 商品卡片等有机体
│ └── ProductCard.vue
└── templates/ # 页面骨架模板
└── ProductPage.vue
这种分层使得组件复用率提升了40%。比如一个AppButton原子组件,既可以被SearchForm分子组件使用,也能直接用在页面级模板中。
2.2 组合式函数的黄金法则
composables目录是Vue3的特色所在。我制定了三条编写规范:
- 所有函数必须以use前缀开头
- 单个文件不超过300行代码
- 必须显式返回响应式对象
典型的useFetch实现:
typescript复制export default function useFetch<T>(url: string) {
const data = ref<T | null>(null)
const error = ref<Error | null>(null)
const fetchData = async () => {
try {
const response = await axios.get(url)
data.value = response.data
} catch (err) {
error.value = err as Error
}
}
return {
data,
error,
fetchData
}
}
踩坑记录:避免在组合式函数中直接修改DOM,这会导致逻辑与视图耦合。曾经有个useModal函数因为直接操作DOM,导致在SSR环境崩溃。
3. 类型系统的深度集成
3.1 组件Props的类型演进
从基础类型到复杂泛型,Props的类型定义经历了三个阶段:
- 基础类型(新手阶段):
typescript复制defineProps({
title: String,
count: Number
})
- 接口定义(中级阶段):
typescript复制interface Props {
title: string
items: Array<{
id: number
name: string
}>
}
defineProps<Props>()
- 泛型组件(高级阶段):
typescript复制interface ListItem {
id: number
name: string
}
defineProps<{
data: T[]
renderItem: (item: T) => VNode
}>()
3.2 类型自动推导的黑科技
通过unplugin-auto-import插件,可以实现API的自动导入和类型推导。在vite.config.ts中配置:
typescript复制AutoImport({
imports: [
'vue',
'vue-router',
{
'@vueuse/core': [
'useMouse',
'useLocalStorage'
]
}
],
dts: 'src/types/auto-imports.d.ts'
})
这能减少30%的手动导入语句,同时保持完整的类型支持。曾经有个项目因为漏导入ref导致生产环境报错,引入自动导入后彻底解决了这
