前面的章节,我们已经一步步实现了一个基本的接口框架,并实现了登录,注册功能和博客文章的添加、删除、修改、查询功能。
那么本章呢,我们来设计一个简单的博客,并展示我们的博客文章,让读者可以阅读浏览。
同时调整我们的项目结构,让整体的扩展性更好,开发更友好。
先看看看整体演示动图效果。
在这里面,我们已经实现了个人博客的以下功能:
- 登录和注册。
- 添加博客文章。
- 删除博客文章。
- 修改博客文章。
- 查询博客文章。
- 查询博客详情。
- 分页查询功能。
那么,接下来,我们来分解一下,在这个改动中,我们调整了哪些东西,以及是如何思考的。
项目结构改动
CoolApi
├── apis
│ ├── admin
│ │ ├── login.js
│ │ └── register.js
│ └── article
│ ├── delete.js
│ ├── detail.js
│ ├── insert.js
│ ├── select.js
│ └── update.js
├── public
│ ├── admin
│ │ ├── article.css
│ │ ├── article.html
│ │ ├── article.js
│ │ ├── index.css
│ │ ├── index.html
│ │ └── index.js
│ ├── blog
│ │ ├── detail.css
│ │ ├── detail.html
│ │ ├── detail.js
│ │ ├── index.css
│ │ ├── index.html
│ │ └── index.js
│ ├── images
│ ├── favicon.ico
│ ├── template-web.js
│ └── utils.js
├── mysql.js
├── package.json
├── server.js
└── routes.js
这是项目的整体结构,为了方便维护,接口用目录进行了区分,分别是 admin(管理接口)
目录和 article(文章接口)
目录。
admin(管理接口)
用来放管理员的注册和登录接口,article(文章接口)
就用来放文章的增、删、改、查接口。
同时,前端页面也分为了 admin(管理后台)
目录和 blog(个人博客)
目录。
管理后台
用来管理博客文章,个人博客
就用来查询文章列表,显示文章内容。
新增了一个 images
目录,用来专门存放图片资源。
项目结构的改动基本就是这么些了,接下来,看看代码逻辑方面的改动。
静态资源改动
// /server.js 文件
// 如果是资源
let staticFile = req.url.split('?')?.[0] || '';
if (staticFile === '/') {
staticFile = '/index.html';
}
if (existsSync(`./public/${staticFile}`) === true) {
res.setHeader('Content-Type', lookup(staticFile));
res.end(readFileSync(`./public/${staticFile}`));
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
}
/server.js
文件的改动如上,处理静态文件部分,额外设置了变量 staticFile
,用来获取请求的路径部分。
比如,查询博客文章详情页面是 https://127.0.0.1:3000/blog/detail.html?id=3
,这个 url
是匹配到的页面是 /blog/detail.html?id=3
。
我们的项目中是没有这个页面的,只有 /blog/detail.html
,所以,我们要把后面 ?id=3
部分给去掉,那么就用这个 staticFile
变量,来提取正确的资源路径。
请求封装改动
const result = await fetch('/api/articleInsert', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify({
title: title,
content: content,
author: user.id
})
});
这是原始的请求方式。
// 请求封装
const utilHttp = async (url, data, action = 'common') => {
// 初始化参数
const params = {
method: 'POST',
headers: {}
};
params.headers['Content-Type'] = 'application/json;charset=utf-8';
params.body = JSON.stringify(data);
// 收到的返回值
const response = await fetch(url, params);
// 把拿到的数据变成JSON结构
const result = await response.json();
return result;
};
// 请求查询接口,拿到文章列表
const { code, data, total, msg } = await utilHttp('/api/article/select', {
page: 1,
limit: 15
});
这是将请求封装后,使用封装函数请求的例子。
可以看到,整体代码都清爽多了。
封装提示弹框
// 显示弹框
const utilShowMsg = (msg, fn) => {
const alertBox = document.createElement('div');
alertBox.textContent = msg;
alertBox.style.cssText = `
position: fixed;
top: 100px;
left: 50%;
transform: translate(-50%, -50px);
background-color: rgba(0, 0, 0, 0.8);
color: #fff;
padding: 20px;
border-radius: 5px;
text-align: center;
z-index: 1000;
`;
document.body.appendChild(alertBox);
setTimeout(() => {
alertBox.remove();
if (fn) {
fn();
}
}, 2000);
};
为了了解操作状态,比如登录是否成功,修改是否成功,封装一个提示函数,用于在相关请求结束后,在页面提示请求返回信息。
大概就是这么些改动,其实也不多,但是对于我们现在项目的维护来说,是非常大的提升。
源码都放在 第2章 源码和开发环境准备章节
了,可以前往自行下载,有任何问题,在专属答疑群艾特我即可。