Skip to content

前面的章节,我们已经一步步实现了一个基本的接口框架,并实现了登录,注册功能和博客文章的添加、删除、修改、查询功能。

那么本章呢,我们来设计一个简单的博客,并展示我们的博客文章,让读者可以阅读浏览。

同时调整我们的项目结构,让整体的扩展性更好,开发更友好。

个人博客基本演示效果

先看看看整体演示动图效果。

在这里面,我们已经实现了个人博客的以下功能:

  1. 登录和注册。
  2. 添加博客文章。
  3. 删除博客文章。
  4. 修改博客文章。
  5. 查询博客文章。
  6. 查询博客详情。
  7. 分页查询功能。

那么,接下来,我们来分解一下,在这个改动中,我们调整了哪些东西,以及是如何思考的。

项目结构改动

bash
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 目录,用来专门存放图片资源。

项目结构的改动基本就是这么些了,接下来,看看代码逻辑方面的改动。

静态资源改动

js
// /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 变量,来提取正确的资源路径。

请求封装改动

js
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
    })
});

这是原始的请求方式。

js
// 请求封装
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
});

这是将请求封装后,使用封装函数请求的例子。

可以看到,整体代码都清爽多了。

封装提示弹框

js
// 显示弹框
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章 源码和开发环境准备章节 了,可以前往自行下载,有任何问题,在专属答疑群艾特我即可。

何以解忧,唯有代码。不忘初心,方得始终。