一. 动机
为什么要写这篇文章呢?我想是为了梳理这个项目涉及到的知识点、技术,以及记录我在做这个项目的过程中的一些感悟与收获,作为一个初学者,希望能帮助到未来的我。尽管这篇文章里面许多东西都在黑马的笔记中详细记载了,但我想的是那终究不是我的,我希望我能在写这篇文章的同时,能够将讲义上的知识逐渐"内化"成我自己的一部分,有所进步。总结就是:
- 梳理
- 理解
- 记忆/录
二. 概述
本篇文章分为三大块。第一块是网页端实现,包括如何进行初始化配置,如何从整体上设计路由,如何对于每一个具体的模块进行设计。第二块是服务器端实现,包括如何进行初始化配置,如何结合api文档实现各种功能。第三块是如何把自己完整的项目部署到云服务器上,最终实现任何人都可以通过ip地址访问完整的项目。
本篇文章差不多算是我在学习过程中接触到的学习资料以及我的一些试错与心得的汇总,具体的学习资料包括黑马程序员的b站课程以及相关实战项目与笔记文档、参考的一些技术帖:
以及我最尊敬的柴特老师(ChatGPT)的指导,在这里向他们表示由衷的感谢!
进一步说,此项目的网页端资料是来源于黑马程序员Vue课程的实战项目。服务器端是在黑马程序员Node.js课程的实战项目的基础上进一步开发,因为此项目与Vue课程的实战项目在api文档上有一些差异。最终部署部分是在两篇上述提到的技术帖的基础上结合柴特老师的指导完成的。项目的api文档是:API文档链接。本项目已经上传到了gitee中,仓库地址是大事件管理系统。
下图是整篇文章的思维导图:

最后来写一段话留给可能存在的读者(目前期望是无),虽然这篇文章是自己学习用,里面估计藏着许多错误,而且写的也很抽象,许多细节都由于本人浮躁而略过,但还是希望能帮到别人。因为我对于编程"开窍"得非常晚,折腾了许久到了研究生才开始系统性地学习开发,这也是我第一次系统性学习的一个阶段性成果。如果因为我的疏忽给你造成了困扰,在这里向你提前表示歉意(哈哈),如果你对此项目有任何疑问,请发邮件向随意提问(我的邮箱)。
三. 网页端实现
3.1 初始化部分
包管理器 pnpm
pnpm 包管理器是现代 JavaScript 生态系统中常用的包管理工具,它用于处理项目依赖和模块。同类工具还有 npm 和 yarn。下表是三者的不同:
特性 / 包管理器 | npm | Yarn | pnpm |
---|---|---|---|
性能和效率 | 适中,对大型项目可能较慢 | 快速,有缓存机制 | 非常高效,节省磁盘空间 |
依赖关系管理 | 扁平的 node_modules 结构 | 扁平的 node_modules 结构 | 非扁平的 node_modules 结构 |
安全性 | 自动安全检查 | 自动安全检查 | 提供隔离的依赖环境 |
工作区支持 | 支持(新版本中) | 有力的工作区支持 | 有效的工作区支持,适合大型项目 |
社区和生态系统 | 广泛的社区和生态系统支持 | 活跃的社区,丰富的插件和集成 | 较新,社区正在增长 |
下图是三者在使用上的差异:
Command | npm | yarn | pnpm |
---|---|---|---|
Install packages | npm install |
yarn |
pnpm install |
Install a package | npm install axios |
yarn add axios |
pnpm add axios |
Install a dev package | npm install axios -D |
yarn add axios -D |
pnpm add axios -D |
Uninstall a package | npm uninstall axios |
yarn remove axios |
pnpm remove axios |
Run a script | npm run dev |
yarn dev |
pnpm dev |
代码规范配置 eslint & prettier
Prettier 是一个工具,专注于美观,用于实现代码格式化,让代码更美观。ESLint 也是一个工具,专注于规范,用于校验错误,检查代码中的错误。现在一般 ESLint 和 Prettier 配合使用。禁用 VSCode 中的 Prettier 插件,使用通过 pnpm 包管理器下载的 Prettier 插件,以及下载 VSCode 中的 ESLint 插件。
.eslintrc.cjs
配置文件用于定义代码规范,其内容包括 Prettier 风格配置,Vue 组件名称多单词组成,以及关闭 props 解构。
代码检查 husky
使用 husky 工具,它是一个基于 Git 的钩子工具,类似于 JavaScript 中的钩子周期,在特定的周期执行特定的操作,用于在代码提交前对代码进行检查。
如何使用呢?分为下面几步:
- 第一步,执行:
git init
,初始化 Git 仓库。 - 第二步,执行:
pnpm dlx husky-init && pnpm install
,安装 husky 工具。 - 第三步,修改:
.husky/pre-commit
文件(定义在提交代码之前要做的事情),删去原有的:npm test
, 换成:pnpm lint
(对项目的所有文件进行检查,对于有错误的地方进行修复)。
然而,如果我的项目很大,husky 对代码进行检查会非常耗时,因此引出了暂存区 ESLint 校验。
如何使用呢?首先安装 lint-staged
插件,pnpm i lint-staged -D
。然后在 package.json
中配置 lint-staged
命令。最后在 .husky/pre-commit
文件进行修改。
调整项目目录
对于使用 pnpm create vue 生成的项目,默认项目目录需要进行进一步调整。主要有以下工作:
- 删除初始化的默认文件,比如
assests
目录下的一些图片,components
目录下默认新建的一些组件等。 - 修改剩余代码内容,比如
router
路由,app.js
,main.js
。 - 新增调整我们需要的目录结构,比如
api
文件夹,utils
文件夹。 - 拷贝初始化资源文件,安装预处理器插件,安装 SASS 预处理器。
关于 Vite 与 Router 的配置
/src/router/index.js
部分代码
javascript
import { createRouter, createWebHistory } from 'vue-router'
// 创建路由实例
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), // .meta.env.BASE_URL vite 中的环境变量 vite.config.js 中的 base 配置项
routes: []
})
createWebHistory()
的参数是所有路径前的前缀,默认是 /
。 .meta.env.BASE_URL
是打包工具 Vite 的环境变量,可以在 vite.config.js
中的 base
配置项进行配置。
/vite.config.js
部分代码
javascript
export default defineConfig({
plugins: [
vue(),
],
base: '/',
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
如果将来部署的域名路径是:http://xxx/my-path/user
,那么可以将 vite.config.js
中的 base
属性更改为:my-path
,这样之后所有的路由都会加上 my-path
。
组件库导入 Element-Plus
Element-Plus 是一个为 Vue.js 3 设计的 UI 框架。首先要进行导入,有全部导入和按需导入两种方法,两者都在官方文档中有介绍。完成按需导入的所有配置之后,可以在项目的任何地方使用 Element-Plus 组件。
用户仓库和持久化 Pinia
Pinia 用于解决多组件共享数据的问题,以及实现代码持久化。
数据交互 Axios
Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js。它提供了请求拦截器和响应拦截器,这些都是中间件,允许你在请求发送到服务器之前以及服务器返回响应之后,但在你的代码处理这些响应之前,对它们进行操作。
-
第一步,创建 Axios 实例,配置超时时间和基础地址。
-
第二步,配置请求拦截器,用于给请求携带 token 等。
-
第三步,配置响应拦截器,用于统一处理响应成功(业务成功,业务失败)和响应失败(401 错误也就是权限不足,token 过期等)。
3.2 整体设计部分
整体路由设计
在整体路由设计阶段,需要明确整个业务的路由规划,包括确定有多少个页面、它们分别在哪个路由下、如何进行页面跳转,以及路由的嵌套关系等。
可以编写一个表格来清晰地记录路由信息,例如:
path | 文件 | 功能 | 组件名 | 路由级别 |
---|---|---|---|---|
/login | views/login/LoginPage.vue | 登录&注册 | LoginPage | 一级路由 |
/ | views/layout/LayoutContainer.vue | 布局架子 | LayoutContainer | 一级路由 |
├─ /article/manage | views/article/ArticleManage.vue | 文章管理 | ArticleManage | 二级路由 |
├─ /article/channel | views/article/ArticleChannel.vue | 频道管理 | ArticleChannel | 二级路由 |
├─ /user/profile | views/user/UserProfile.vue | 个人详情 | UserProfile | 二级路由 |
├─ /user/avatar | views/user/UserAvatar.vue | 更换头像 | UserAvatar | 二级路由 |
├─ /user/password | views/user/UserPassword.vue | 重置密码 | UserPassword | 二级路由 |
编写完表格后,可以根据路由信息一次性配置或逐个配置路由。
3.3 实现部分
在编程部分,针对每个具体的页面,结合 Element Plus 组件库进行编程。
登录注册页面
在登录注册页面中,涉及到的 Element Plus 组件有:el-row
、el-col
、el-form
(el-form-item
)、el-input
、el-button
。需要注意的细节包括:
-
实现表单数据校验,最好与后端的校验规则保持一致。
-
所有与服务器端的交互请求都应封装在
api
文件中。
首页布局页面
在首页 Layout 架子中,涉及到的 Element Plus 组件有:el-container
(el-aside
、el-header
、el-main
)、el-dropdown
、el-menu
(el-menu-item
)、el-icon
、el-sub-item
。需要注意的细节包括:
- 登录拦截访问,只有登录页可以未授权访问,其他所有页面都需要先登录。
文章分类管理页面
在文章分类管理页面中,涉及到的 Element Plus 组件有:el-card
、el-table
(el-table-column
)、el-dialog
。需要注意的细节包括:
- 可以将添加分类和编辑分类所共用的弹层封装成一个组件(存放在
views
文件夹下)。
文章详情管理页面
在文章详情管理页面中,涉及到的 Element Plus 组件有:el-select
(el-option
)、el-pagination
、el-drawer
、el-upload
。需要注意的细节包括:
- 国际化处理,将 Element Plus 组件库中的默认语言从英文切换到中文。
- 可以将添加详情和编辑详情所共用的抽屉页面封装成一个组件。
- 使用富文本编辑器,例如 Vue Quill。
用户信息管理相关页面
无
四. 服务器端实现
4.1 初始化部分
在服务器端初始化部分,需要进行以下操作:
-
创建项目:使用
npm init -y
创建一个新的项目。 -
安装 Express 框架:使用
npm install express
安装 Express 框架。 -
配置 CORS 跨域:确保服务器允许跨域请求,可以使用 CORS 中间件来处理跨域问题。
-
配置解析
application/x-www-form-urlencoded
格式表单数据的中间件,通常使用body-parser
中间件来实现。 -
初始化
router
和router_handler
文件夹,用于组织路由和请求处理逻辑。 -
优化
res.send()
代码,确保服务器端返回响应的格式正确。
4.2 整体设计部分
在服务器端设计部分,主要是根据客户端已经设计好的 API 接口,逐个实现这些接口的逻辑。
4.3 编程部分
在服务器端编程部分,需要实现各个功能模块的具体逻辑,以下是两个主要功能的相关细节:
登录注册功能
在登录注册功能的实现中,需要考虑以下细节:
- 密码相关:使用
bcryptjs
对用户密码进行加密,同时使用bcrypt.compareSync()
验证密码是否正确。 - 数据库操作:通过检查
results.length
和results.affectedRows
来判断数据库操作是否成功。 - 表单验证:使用
joi
定义验证规则,然后使用expressJoi
注册验证中间件进行验证。 - Token 相关:使用
jsonwebtoken
生成 token 字符串,使用express-jwt
注册解析 token 的中间件。 - 数据格式:考虑数据格式问题,特别是 dataURL 格式,允许以 Base64 编码的字符串形式直接嵌入文件内容到文档中,避免进行额外的 HTTP 请求。通常用于嵌入图像、字体文件或其他小文件到 HTML 或 CSS 文件中。
文章详情管理功能
在文章详情管理功能的实现中,需要处理以下细节:
- 表单数据格式:HTTP 请求中常用的两种表单数据格式为
form-data
和x-www-form-urlencoded
。application/x-www-form-urlencoded
格式将表单数据编码为键值对,进行 URL 编码,适合发送简单的文本数据。multipart/form-data
格式通常用于表单提交,特别是涉及到文件上传时,因为它允许在单个请求中发送多种类型的数据。 - 使用
multer
中间件来解析form-data
数据,通过dest
属性指定文件存储位置,然后在路由请求中添加中间件,单独解析其中的某一个元素,并将其存储到之前指定的存储位置,并在req
中增加一个file
属性来存储文件对象。 - 使用
express.static()
来将uploads
文件夹中的图片托管为静态资源,这样不需要额外处理,可以直接访问uploads
目录下的文件。
五. 部署到云服务器
5.1 准备云服务器
在部署到云服务器之前,需要准备一个云服务器。我使用的是腾讯云的轻量应用服务器,第一次可以免费试用。配置如下:
-
CPU: 2核
-
内存: 2GB
-
系统盘: SSD云硬盘 40GiB
-
流量包: 200GB/月(带宽: 3Mbps)
-
系统: CentOS 7.6
5.2 安装必要的软件
在云服务器上进行部署之前,需要安装一些必要的软件和工具,比如:
-
更新系统软件:使用
yum update -y
命令来更新系统上的软件包。 -
安装一些常用的软件包,根据个人习惯可以选择安装,比如
curl
,vim
,wget
,unzip
,git
,nano
等。 -
安装宝塔面板:宝塔面板是一个可视化界面工具,用于管理 Linux 服务器。为什么安装宝塔面板呢?因为之后上传项目的时候通过宝塔面板会方便许多。可以使用以下命令来安装宝塔面板:
shell
yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh
安装完成后,宝塔面板可以帮助我们更轻松地管理服务器和部署应用。

- 安装 Web 服务器,用于托管和管理网页端。我选择了安装 Nginx 作为 Web 服务器。使用以下命令来安装 Nginx:
shell
yum install nginx -y
在使用 yum 命令时,-y 选项表示自动应答 "yes",即在安装软件包或执行操作时,自动接受所有确认和提示,无需手动确认。安装完成后,需要启动 Nginx 服务,并配置相关参数,确保 Web 服务器可以正常运行,相关命令如下:
开启防火墙:
bash
systemctl start nginx
启动Nginx:
sql
service nginx start
重启Nginx:
bash
nginx -s reload
关闭Nginx:
bash
service nginx stop
Nginx 启动成功后,在浏览器中输入主机名(公网ip),看是否启动成功。如果出现无法访问此网站,检查是否在服务器上开通端口,如果没有设置端口号,则网站无法访问。配置完端口后再继续操作。配置端口后,终端中输入nginx -s reload
,重启Nginx服务。重启Nginx后,在浏览器中输入主机名(公网ip),看是否启动成功
在终端执行上述代码的过程中可能会遇到一些报错,借助ChatGPT工具,只要有耐心,就可以解决。
5.3 部署应用
网页端(app_client)
在部署网页端应用时,需要完成以下步骤:
-
打包项目:使用 Vite 打包项目,执行命令
pnpm build
。这将触发 Vite 进行项目构建,并生成一个名为dist
的文件夹。dist
文件夹包含了构建后的 Web 应用程序,用于部署到服务器上。 -
配置 Nginx 代理:找到系统
/etc/nginx/conf.d
目录,此时目录应该有一个默认的default.conf
,新建一个文件,后缀为.conf
。我这里新建了一个bigevent.conf
,文件内容如下:nginxserver { listen 3000; # 端口号 server_name 82.157.198.151; # 域名或公网 IP root /www/projects/app_client; # 文件的路径 index index.html; # 配置默认访问的页面 location /api { proxy_pass http://127.0.0.1:3033; } location /apilist { rewrite /apilist/(.*) /$1 break; proxy_pass http://127.0.0.1:3033; } location / { try_files $uri $uri/ /index.html; } }
重点是server_name, root和index。server_name可以是注册的域名,也可以是云服务器的公网ip。root填写web服务器的根目录,服务器将在这个目录下查找文件来响应来自浏览器的请求。index是配置默认的访问页面,如果用户访问一个目录而没有指定具体文件名,Nginx将尝试使用
index.html
作为默认页面。这意味着当用户访问根目录时,Nginx会尝试提供index.html
文件。 -
将打包后的
dist
文件夹放入服务器中的指定目录,通常是 Nginx 配置中的root
目录,这里是/www/projects/app_client
。我使用宝塔面板直接将dist
文件夹上传 -
重新加载 Nginx 配置文件,使用命令
/usr/sbin/nginx -s reload
来重启 Nginx 服务。这样,网页端应用就可以通过公网 IP 或域名访问了。

服务器端(app_server)
在部署服务器端应用时,可以按照以下步骤进行:
-
将
app_server
文件通过宝塔面板上传到服务器指定的文件夹。我选择的路径是/www/projects/app_server
。如果文件数量过多,可以将它们压缩成一个压缩文件,上传后再解压。
-
安装 Node.js 环境。
shell
sudo yum install -y nodejs
这里由于操作系统老旧的缘故,可能这样下载nodejs版本由于依赖库版本问题不兼容,最终无法正常安装。通过NodeSource可能也会因为不再维护的关系无法正常安装nodejs。我最终选择使用 NVM(Node Version Manager)进行安装。步骤如下:
-
使用淘宝 NVM 镜像下载 NVM:
shellcurl -o- https://gitee.com/mirrors/nvm/raw/master/install.sh | bash
-
新加载 Shell 配置:
shellsource ~/.bashrc
-
安装 Node.js 14:
shellnvm install 14 nvm use 14
可能在按照上面步骤安装的过程中会出现许多报错,但只要有耐心,借助ChatGPT,一定能顺利解决!(不能把ChatGPT当成万能工具,自己却成为一个不思考的复制粘贴机器,使用ChatGPT最高小的方式应该是 思考为主 + ChatGPT为辅)
- 安装 MySQL 数据库。下面是相关命令:
安装 MySQL:
shell
yum install mysql
启动 MySQL 服务:
shell
systemctl start mysqld
检查 MySQL 服务状态:
shell
systemctl status mysqld
停止 MySQL 服务:
shell
systemctl stop mysqld
设置 MySQL 开机自启动:
shell
systemctl enable mysqld
由于CentOS7.6版本问题,大概率安装的MySQL服务端和客户端会出现不兼容问题,我在执行时出现了报错:
shell
{
"code": 1,
"message": "ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client"
}
这里表示数据库客户端不支持服务器要求的身份验证协议。这通常发生在MySQL 8.0及以上版本中,因为从MySQL 8.0开始,默认的身份验证插件从mysql_native_password
更改为caching_sha2_password
。为了解决这个问题,我的方式是更改用户的身份验证插件。首先以root用户登录MySQL,执行如下命令来将MySQL用户的身份验证插件更改回mysql_native_password
。
-
运行服务器端应用。
首先,全局安装
nodemon
,它可以监视文件变化并自动重启服务器。如果尚未安装,可以运行以下命令进行安装:shellnpm install -g nodemon
进入服务器端应用的项目目录:
shellcd /www/projects/app_server
安装应用的依赖项:
shellnpm install
使用
nodemon
代替npm
来运行项目:shellnodemon app.js
这将启动服务器端应用,并使其在代码变化时自动重启。项目现在应该成功运行。
