前言:本文是「Koa2 实战:从零构建 Node+Koa2+MongoDB+Vue 移动端全栈项目」的第二篇,如果您还没有阅读第一篇,建议先阅读第一篇,再看本文。
在前一篇文章中,我们已经成功的搭建了我们的项目架构,学习了如何使用 Koa2 进行接口开发。接下来,我们将更进一步,学习使用 MongoDB 存储我们的数据,同时使用 Vue.js 开发我们的前端项目。
数据库与数据模型
在本项目中,我们选择使用 MongoDB 作为我们的数据库,这个决定的原因主要是 MongoDB 的数据存储方式和格式,比较契合我们这种非关系型数据的存储需求。
安装 MongoDB
首先,我们需要安装 MongoDB,可以在官网中下载对应系统的 MongoDB 安装包,安装完成后,我们需要手动创建 MongoDB 的数据保存路径。
假设我们的 MongoDB 数据是保存在本地的 data 目录中,在命令行中运行以下命令:
mkdir ~/data mkdir ~/data/db
Mongoose
作为 Node.js 中一种非常成熟的 ORM 框架,Mongoose 提供了非常方便的 API 以使得我们能够轻松地连接 MongoDB 数据库,并且操作数据模型。我们可以使用 npm 或者 yarn 进行安装。
npm install mongoose --save
数据模型设计与定义
在项目中,我们的常见数据模型包括用户、文章、评论等功能模块。下面,让我们以用户模型为例,简单介绍如何定义一个数据模型。
在 server/models
目录下,我们新建一个 user.js
文件,这是我们定义用户模型的文件。我们在文件中使用 Mongoose 的 Schema
和 model
,实现定义和导出一个 User
类。
-- -------------------- ---- ------- ----- -------- - ------------------- ----- ------ - --------------- ----- ---------- - --- -------- --------- - ----- ------- ------- ----- --------- ---- -- --------- - ----- ------- --------- ---- -- ------ - ----- ------- ------- ----- --------- ---- -- ------- - ----- ------ -- ------------ - ----- ------ -- ---------- - - ----- ---------------------- ---- ------ - -- ---------- - - ----- ---------------------- ---- ------ - -- -- - ----------- ---- -- ----- ---- - ---------------------- ----------- -------------- - ----
在上述代码中,我们定义了 User
的 Schema 设计模型,包含了:
userName
:用户名,通过unique
、required
等策略来保证唯一性和必要性。password
:密码,同样需要加密和保护,在我们后面的实现中,我们会学习到如何进行密码处理和保护。email
:邮箱,同样需要确保唯一性和必要性。avatar
:用户头像,不是必需项,因此不需要加required
属性。description
:用户描述,不是必需项,因此不需要加required
属性。following
、followers
:这里是用户与用户之间的关注关系,这里使用了 mongoose 自带的ref
语法,来实现 User 之间的引用。
注意这里是如何使用 Mongoose Schema 实现定义数据模型的。
连接数据库
在现代开发中,我们的代码往往分为 controller、model、service 三个逻辑层。model 层提供对数据存储、关系维护的支持。因此,在我们的项目中,我们需要编写一个 MongoDB 连接的模块进行数据库的连接操作。
在 server/connectDB.js
文件中,我们实现 MongoDB 的连接和操作。
-- -------------------- ---- ------- ----- -------- - ------------------- ----- ----- - ---------------------------------------- ----------------------- - ---------------- ----- ------------------- ---- -- ----------------------------------- -- -- - --------------------- ---------- ---- -- ---------- -- ------------------------------- ----- -- - --------------------- ---------- ------ -------- -- -------------------------------------- -- -- - --------------------- ---------- -------------- -- -------------- - --------
在上述代码中,我们使用 mongoose.connect()
进行数据库连接,对于连接成功、失败、断开等情况使用 mongoose.connection.on()
绑定事件监听器,以便于在连接过程中不同的阶段中,向控制台输出对应的信息。
应用修改
上述步骤都完成后,我们需要将上述代码整合到我们的项目中。首先,我们在 app.js
中引入 mongoose
,并且调用 connectDB.js
。
const mongoose = require('./connectDB') mongoose.Promise = global.Promise
在上述代码中,第一行代码引用了 mongoose
,并且 connectDB.js
建立了连接,这里需要指定 Promise
类型为全局的 Promise
。
使用 MongoDB 存储用户
接下来,我们要为我们的注册接口实现数据保存操作,更具体的,就是将用户数据存入到 MongoDB 的 Users
集合中。下面是实现 register
API 的核心代码。
-- -------------------- ---- ------- ----- ---- - ------------------------- -------------- - - ----- ------------- - --- - ----- - --------- --------- ----- - - ---------------- ----- ---- - --- ------ --------- --------- ----- -- ----- ------ - ----- ----------- -------- - - -------- ----- ----- ------ - - ----- ----- - -------- - - -------- ------ -------- ----------- - - - -
在上述代码中,我们引入 user
的数据模型,并且使用 ctx.request.body
实现读取出用户提交的用户名、密码、邮箱等数据,并且将其实例化成一个 User 对象,通过实例对象的 save()
方法实现保存操作。
前端项目搭建
接下来,我们使用 Vue.js 来搭建我们的前端项目。在本项目中,我们将会使用 Vue.js 进行开发。
在开始这一步之前,我们需要了解关于 Vue.js 的常用开发模式、框架和插件。 比如说:
- 模块化开发:使用 Vue.js 的组件开发模式,将页面拆分成多个组件,以适应复杂页面的设计。
vue-router
:前端路由,实现 SPA(单页面应用程序)。vuex
:前端状态管理,用于管理全局状态和数据。
创建 Vue 项目
在命令行中输入以下命令创建一个新的 Vue 项目:
vue create my-project
这里使用了 Vue.js 提供的脚手架工具创建了一个新的 Vue.js 项目。这里面可以进行配置、安装插件等操作,其中可以选用典型的 Babel 7+Linter/Formatter 和 ESlint + Prettier/Standard,以进行代码风格管理。
在创建成功之后,可以使用以下命令启动项目:
cd my-project npm run serve
这样,在运行时,你可以在浏览器中通过 http://localhost:8080/
访问到我们的 Vue 项目。
安装依赖
由于我们的项目中要用到很多依赖项,因此,在进入项目目录后,先使用以下命令安装我们的依赖:
yarn add axios moment vee-validate babel-runtime vue-router vuex vuex-persistedstate vuex-router-sync
这里简单介绍一下这些依赖的作用:
axios
:处理前端与后端接口交互。moment
:用于处理时间戳格式。vee-validate
:功能强大、灵活的表单数据验证器。babel-runtime
:用于转换 ES6 代码为 ES5 代码。vue-router
:实现前端路由。vuex
:用于前端状态管理。vuex-persistedstate
:状态持久化,保证状态管理数据不被刷新清空。vuex-router-sync
:路由管理、状态管理同步处理。
项目目录结构设计
在前端项目中,我们使用 Vue.js 进行开发,而在 Vue.js 的项目开发中,我们的代码往往规划为:
components
:存储 Vue 公共组件。router
:Vue Router 模块。store
:Vuex 模块。views
:存储项目页面。App.vue
:根组件。main.js
:入口文件。static
:存储静态资源。public
:存储公共资源和模板 HTML。
下面是我们的项目结构图:
-- -------------------- ---- ------- ----------- --- ---- - --- ------- - --- ------ - --- ------ - --- ----------- - --- ------- - --- ------ - --- ------- - --- ------- - --- --------- --- ----- --- ------------- --- ------------ --- ---------------
在上面的项目结构中,我们使用了常见的 web 开发者的一种目录结构设计方式,使得每个模块、组件、页面之间可以相互独立并且呈现出严谨的目录结构。
配置 Vue.js
在使用 Vue.js 进行开发时,我们需要在 public/index.html
的 head
标签中引入 vue.js
。
<body> <div id="app"></div> <!-- built files will be auto injected --> <script src="/js/vue.js"></script> </body>
引入 Vue Router
我们使用 vue-router 实现前端路由功能。在本项目中,我们需要配置以下两个文件:路由配置 router.js
和路由守卫配置 auth.js
。
在 router.js
文件中,我们可以简单地定义路由配置并且使用 Vue Router 中的 router.beforeEach()
实现路由守卫。
-- -------------------- ---- ------- ------ --- ---- ----- ------ ------ ---- ------------ ------ ----- ---- ---------- --------------- ----- ------ - - - ----- ---- ----- ------- ---------- -- -- --------------------------- -- - ----- --------- ----- -------- ---------- -- -- ---------------------------- -- - ----- ------------ ----- ----------- ---------- -- -- ------------------------------- -- - ----- --------------- ----- ---------------- ---------- -- -- ------------------------------------ -- - ----- ------ - --- -------- ----- ---------- ----- ----------------------------- ------ -- ----------------------- ---- ----- ----- -- - ----- ------- - ------------------- -- ---------------------- -- -------- --- -------- -- ------- --- ------------ - -- ------------------- ------ - ---- -- ---------- - -- -------- -- --------------------------------- -- ------------------------------ - ------------------------- ------------------------------ ---------------------------- --------------------------------- ------ - ---- - -------------- - - ---- - ------ - -- ------ ------- ------
在上述代码中,我们首先引入了 Vue Router,使用 Vue.use(Router)
进行初始化。然后在 routes
中定义了几个常见的路由规则,并且使用 router.beforeEach()
配置路由守卫功能。如果用户没有登录,并且目标路径不是 /login
,我们要求其跳转到登录页面,如果用户已登录,则直接放行,即进入到目标路由对应的页面。
使用 Vuex 实现全局状态管理
在前端项目中,由于有很多数据需要在组件间传递和共享,如果每次都需要在组件间传递,那么就会非常繁琐,并且维护性也很差。而使用 Vuex,可以非常方便地实现全局状态管理,方案极佳。因此,在本项目中,我们将使用 Vuex 进行全局状态管理。
在 src/store/
目录下我们新建 index.js
作为我们的 Vuex Store。
在 index.js
文件中,我们将集中存储我们 Web 项目中常见的配置、常量、状态等数据。同时,也可以在这里定义数据修改的行为模块:
-- -------------------- ---- ------- ------ --- ---- ----- ------ ---- ---- ------ ------ -------------------- ---- --------------------- ------ - ---- - ---- ------------------ ------ ------- ---- ---------- ------------- ----- ----- - - ---------- ------ --------- --- ------ -- - ----- --------- - - --------------- ------- ---------- -- - --------------- - --------- -- ------------- ------- --------- -- - -------------- - -------- -- ---------- ------- ------ -- - ----------- - ----- - - ----- ------- - -- ----- ------- - - ---------------------- -------- -------------------- ------- ----- - ------ - -- ------------------------- ------ ---------- --------- ------------ - - -- - ----- ----- - --- ------------ ------ ---------- -------- ------- -- ----------- -------- ------ ------- -----
在 index.js
中,我们使用了常见的配置 state
、mutations
、actions
,以及使用 Vuex 插件进行状态持久化。使用 sync()
配置路由状态和 store 状态的绑定。
通常情况下,外部组件是无法理解 Vuex 的实现方式和原理的,因此我们使用 Vuex 中的 vuex-persistedstate
实现状态持久化,保证数据信息在页面刷新后也不丢失。
项目 API 模块设计
在 Vue.js 项目中,通常需要频繁调用 API 接口与服务器进行通讯,这里我们可以把所有接口都统一通过一个 api 模块来进行管理。
在 src/api
目录下,我们新建一个 index.js
文件用于管理所有的 APIs,我们需要针对不同实体进行管理。
在该文件中,我们会根据不同的接口实现不同的 RESTful API 风格。
-- -------------------- ---- ------- ------ ----- ---- ------- ----- ------- - ---------------------------- ----- -------- - -------------- -------- -------- -------- ----- -- ----- ------- - ----- ------- ------ - --- ---- - --- ------- - --- -- - ----- ------- - - ---- ------- --------------------- ------- ----- ------- - ------------------------ - ----------------------------- -- -- ------ ----------------- - ----- --- - - -- ---- -------------- - ------ ------------------------- ------- --- ----- -- ----------- - ------ ---------------------- ------- --- ----- -- ----------- -- - ------ --------------------- ------ -- -- ---- ---------------- - ------ ------------------- ------ -- -------------------- - ------ ------------------------- ------ -- ---------------------- - ------ ------------------- ------- --- ----- -- --------------------- - ------ ------------------------- --------- - - ------ ------- ---
在上述代码中,我们使用了 Axios.js 来实现与服务器的接口交互,并且通过 api
对象暴露RESTful API 接口。对于接口调用,我们需要提供对应的参数、数据、请求方式,并且附带 token 等其他信息。
编写页面组件
在 Vue.js 中,我们可以通过编写组件来实现页面的构建,这里简单以首页(Home.vue
)为例,展示页面组件的编写实践:
-- -------------------- ---- ------- ---------- ---- ----------------------- -------- ------- ----------- ------------ -------------------- ---------- -- --------- ------- ----------- ---- ------------------- ---- ------------------ --- --------------------- ------- ------------------------------ ---------- ---------- -- ------ -- --- -- ------- -------------- ----------------- ----------- --------- ------ ------ --------- --------- ------ ----------- -------- ------ ----------- ---- ------------------------------ ------ --- ---- ------- ------ ------- - ----- ------- ----------- - ----------- -- ------ - ------ - ---- --- ----- --- ------------- --- --------- -- - -- ----- --------- - --------------------- ----------------- -- -------- - ----- ---------------- - ----- --- - ----- -------------------- -- ------------------ - ------------- - ------------- -- -- - -- ----- ------------ - ----- --- - ----- ------------- -- ------------------ - ----- - ----- ------------ - - ------------- --------- - ---- ----------------- - ------------ - -- ----- --------------------- - -------- - --- ----- --- - ----- ------------------------- -- ------------------ - ------------- - ------------- - - - - ---------
在上述代码中,我们首先引入了查询用的 API 接口。使用 ArticleList
组件展现我们的文章列表,使用 Home-right
组件渲染右侧模块分区。
Home.vue
主要实现了以下功能:
- 使用了
api.getAllArticles()
获取文章列表,使用ArticleList
展示数据。 - 还使用了
api.getTags()
获取标签总数以及总数列表,使用tags
数组渲染标签列表,点击标签时可以再次查询对应标签的文章列表。
安装 Element UI
Element UI
是由饿了么前端团队所开发的一套符合Vue.js
美学的前端UI组件库,适用于快速构建Web应用界面。在本项目中,我们也会使用它进行后台管理页面的布局及组件构建。
在使用 npm
/ yarn
安装 Element UI 前,我们需要先安装 node-sass
、sass-loader
和 less
,在安装这些之前,我们需要使用管理员权限启动命令行(也称为“管理员模式”)。
npm install node-sass sass-loader less less-loader --save-dev # 或者你可以先全局安装 sass,下面的则可以不装 npm install -g sass
安装完上述依赖后,我们再来安装 Element UI
:
npm i element-ui -S
在我们需要使用 Element UI
的 Vue 组件中,我们需要将 Element UI
组件在该页面下,进行主题的统一调配:
-- -------------------- ---- ------- -- ----------------------------- ------- ---------------------------------------------------------------------- -- -------- ------- ---------------------------------- ----------------- -------- ------- -----------------------
上述样式文件是 Element UI
样式文件的一个扩展。在该样式文件中,我们可以更方便、快捷的修改 Element UI
组件中的样式。同样在全局 app.scss
文件中引入该样式文件,以确保样式覆盖和全局样式的展示统一性。
总结
在本篇文章中,我们学习了如何通过 MongoDB 存储我们的数据,并且利用 Vue.js 构建前端界面,同时使用 Vuex 实现了全局状态管理。通过组件、路由、状态管理等多种手段,我们成功地构建了一个功能完整的 web 项目,展示了项目的开发流程和实践方法。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65aa4bf2add4f0e0ff3e8607