🦄 2024 独立开发者训练营,一起创业!(早鸟优惠在5天后结束)查看介绍 / 立即报名 →

Vue:设计一个经得起实战的应用项目结构


图:Mathieu L.B

开发一个应用最难的事情就是给各种东西起名字,还有就是用什么方法组织各种东西的文件。今天跟大伙分享一个经过我实践之后的一个 Vue 项目结构。Vue 是一个前端应用框架,它只给我们制造零部件的方法与材料,但是并没告诉我们项目如何组织。好处是这很自由,怎么整都行,坏处也是很自由,因为我们自己要做很多决定,每次决定都会消费一点脑力,所以一开始你会很头痛。

语言

我在 Vue 项目里使用了 TypeScript,这比直接用纯的 JavaScript 开发的项目复杂一点点,你需要考虑各种东西的类型。但我觉得一开始不需要想太多类型的事儿,只要编辑器不报类型的错误,我就不管类型的事儿。加上 Vue 官方暂时还没有提供关于用 TypeScript 开发的文档,所以可以再等一等。不过我们还是可以在项目里用一下 TypeScript,会有一些好处,但不用太费力气研究类型。

目录结构

应用整体相关的东西我会把它放在 app 这个目录里面,应用里的资源我会单独放在各自的目录下面。

应用目录

我会把应用整体相关的东西全部放在 src/app 的下面,比如应用的路由器,路由守卫,Store,Store 插件,应用配置等等。每种东西我只会创建一个文件,文件名我会用 app 作为前缀,后面接着零部件的名字,比如 app.router 文件里定义的就是应用的路由器,app.store 里面定义的是应用的 Store。

├── app
│   ├── app.config.ts
│   ├── app.mixin.ts
│   ├── app.router.guard.ts
│   ├── app.router.ts
│   ├── app.routes.ts
│   ├── app.service.ts
│   ├── app.store.plugin.ts
│   ├── app.store.ts
│   ├── app.vue

app.vue 是应用的根组件(Root Component),创建 Vue 应用的时候会用到这个组件。app.config 是应用里面需要的一些配置,在应用里如果需要配置信息,可以导入使用在这个模块里导出的配置信息。

组件

在应用全局范围或者经常用到的一些组件可以放在 src/app/components 目录的下面,比如 app-icon 是应用的小图标组件,app-logo 是应用的标志。

├── app
│   ├── ...
│   ├── components
│   │   ├── app-home.vue
│   │   ├── app-icon.vue
│   │   ├── app-logo.vue

零部件

应用的布局,或者在应用全局经常用的一些功能,可以放在 src/app 下面的一个单独的目录里面。比如在 notification 目录里面,定义了应用的通知提醒功能,目录里面包含了功能需要的组件,样式还有 Store。

├── app
│   ├── ...
│   ├── notification
│   │   ├── app-notification.store.ts
│   │   ├── app-notification.vue

资源目录

应用里的资源或者应用做的事情都可以单独放在各自的目录下面,如果你的应用里出现的资源并不多,可以直接在 src 目录下面创建目录。如果有很多资源,可以给它们分分组,然后在每个群组目录的下面再去创建独立的目录。

├── post
│   ├── post.store.ts
│   ├── post.service.ts
│   ├── post.routes.ts
│   ├── components
│   ├── create
│   ├── update
│   ├── show
│   └── index

在 src/post 这个目录里存放的是我应用里的内容资源相关的东西。post.store 是资源需要的 Store 模块,post.service 里面可以定义一些需要的服务方法,post.routes 定义的是资源相关的路由,components  目录下面是一些共用的组件。

动作/操作

根据对资源做的不同的事情,我又会分成几个不同的目录,比如 create 里面放的是创建 post 这种资源用的东西,update 指的是更新资源,show 里面的东西是资源的独立页面,index 里面的东西是资源列表。

│   ├── index
│   │   ├── components
│   │   │   ├── post-list-filters.vue
│   │   │   ├── post-list-item.vue
│   │   │   ├── post-list.vue
│   │   │   └── styles
│   │   │       ├── post-list-filters.css
│   │   │       ├── post-list-item.css
│   │   │       └── post-list.css
│   │   ├── post-index.store.ts
│   │   └── post-index.vue

每个动作目录里面又包含了组件,样式,还有 Store。在动作目录的根目录下面有一个主组件,比如在 src/post/index 的下面,就会有一个 post-index.vue 这个组件。在 src/post/create 的下面,会有一个 post-create.vue 。这些主组件一般会作为路由组件,比如你在 post.routes 里面定义了一条内容列表路由,路由对应的组件就是 post-index 。

资源动作需要的其它组件可以放在 components 目录里面,比如在 src/post/index/components 里面, 有 post-list,post-list-item 这些组件。在 post-index 里面会使用 post-list,在 post-list 里面会使用 post-list-item ,在 post-list-item 里面又会用到一些组件,这些组件都可以放在这个 components 里面。

样式

在单文件组件里,你可以直接在组件的样式放在 style 标签里面,不过我偏好创建独立的样式文件,文件的名字跟组件的名字保持一致,然后在 style 标签里使用 @import 导入这个样式表。样式表文件一般都放在组件当前目录下面的 styles 这个目录里面。比如 src/post/components/post-list.vue 这个组件的样式表,位置就是 src/post/components/styles/post-list.css 。

Store

我的这个应用使用 Vuex 管理应用的状态,所以需要创建一些 Store 。注意在实际的应用中,一个 Store 模块是不够用的,即使你把 getters,mutations,actions 分割成不同的模块,也是不够的,因为很快就会陷入混乱之中。我的做法是按资源或者要做的事情去创建多个 Store 模块,模块里使用命名空间,这样你就会清楚的知道在应用里需要的数据或者动作来自哪里。

应用的 Store 我分成了三个级别,应用、资源、资源操作。在应用 Store 里注册使用资源  Store,在资源 Store 里注册使用资源操作 Store 模块。

示例:

├── app
│   ├── app.store.ts
├── comment
│   ├── comment.store.ts
│   ├── create
│   │   └── comment-create.store.ts

comment-create.store 是创建评论需要用的 Store,comment 下面的  comment.store 是评论资源整体的 Store,在它里面会注册使用 comment-create.store 。app.store 是应用整体的 Store 模块,在它里面会注册使用 comment.store。

这样如果我想在组件里使用 comment-create.store 里面定义的 createComment 动作。位置就是 comment/create/createComment。 这个路径就说明了我在 app.store 里注册使用 comment.store 的时候,用的名字叫 comment,我在 comment.store 里注册使用 comment-create.store 的时候,用的是 create 这个名字。

在组件里,你可以使用 Vuex 提供的帮手方法,把 Store 里的东西直接映射到组件里使用,像这样:

methods: {
  ...mapActions({
    createComment: 'comment/create/createComment'
  }),
}

这样你就可以直接在 Vue 组件里调用 createComment 这个方法了,实际上执行的就是在 comment-create.store 里定义的 createComment 这个动作。如果你不用帮手方法做映射,也可以直接使用 $store 上的 dispatch 方法,派发这个动作,像这样:

this.$store.dispatch('comment/create/createComment');

路由

我会在 app 目录里面定义一个路由器(router),然后交给 Vue 应用使用。路由器需要的路由可以单独放在资源各自的目录下面,比如在 post 目录里面会有一个 post.routes.ts ,在这个文件里你可以定义跟内容相关的路由。定义之后在应用的路由器里面需要导入使用 post.routes.ts 里定义的路由。

src/post/post.routes.ts

/**
 * 定义路由
 */
const routes: Array = [
  {
    name: 'postIndex',
    path: '/posts',
    component: PostIndex,
    props: route => {
      return {
        sort: 'latest',
        filter: route.query,
      };
    },
  },
];
/**
 * 默认导出
 */
export default routes;

src/app.router.ts

import postRoutes from '@/post/post.routes';
/**
 * 创建路由器
 */
const router = createRouter({
  history: createWebHistory(),
  routes: [...postRoutes],
});

配置

在 src/app/app.config.ts  里面的东西是应用相关的配置,内容大概像这样:

/**
 * 服务接口基本地址
 */
export const API_BASE_URL = process.env.VUE_APP_API_BASE_URL;

在配置文件里可以导出一些配置,这些配置的值大部分都来自环境变量。你可以在项目根目录的下面,创建一个 .env.development,为开发环境准备一些环境变量,在 .env.production 文件里定义在生产环境中使用的环境变量。

VUE_APP_API_BASE_URL=http://localhost:3000

这些环境变量的名字要用 VUE_APP_ 开头,Vue 在编译的时候会自动把这些环境变量替换成真实的值。

结语

上面就是我要跟大家分享的 Vue 项目结构,我在一个 Vue 项目里使用了这个结构,感觉不错,希望能给大家一个参考。研究它也花了我不少功夫,不要小看它,每个细小的决定都需要花点时间想一想。

另外我基于这个结构开发了一个 Vue CLI 插件,可以快速使用命令生成需要的组件,还有 Store,还可以自动在指定的父辈那里导入使用这些新生成的东西,省去了很多事儿,后面我会整理一下,再跟大家分享一下这个命令行工具。

宁皓网的 Vue 课程已经开始了,你可以从头开始,学会使用 Vue 框架提供的各种东西,掌握用 Vue 框架开发应用的全部技能。欢迎大家订阅宁皓网,现在订阅可以多送一年时间,老用户重新订阅或者续订可以多送两年,谢谢大家:)  点击订阅

微信好友

用微信扫描二维码,
加我好友。

微信公众号

用微信扫描二维码,
订阅宁皓网公众号。

240746680

用 QQ 扫描二维码,
加入宁皓网 QQ 群。

统计

14696
分钟
0
你学会了
0%
完成

社会化网络

关于

微信订阅号

扫描微信二维码关注宁皓网,每天进步一点