koa react mysql_React + Koa + Mysql 构建个人博客

前言

由于一直在用 vue 写业务,为了熟悉下 react 开发模式,所以选择了 react。数据库一开始用的是 mongodb,后来换成 mysql 了,一套下来感觉 mysql 也挺好上手的。react-router、koa、mysql 都是从0开始接触开发的,期间遇到过很多问题,印象最深的是 react-router 参考官方文档配置的,楞是跑不起来,花费了好几个小时,最后才发现看的文档是v1.0, 而项目中是v4.3, 好在可参考的资料比较多,问题都迎刃而解了。

博客介绍

前端项目通过 create-react-app 构建,server端通过 koa-generator 构建

前后端分离,博客页、后台管理都在 blog-admin 里,对含有 /admin 的路由进行登录拦截

前端: react + antd + react-router4 + axios

server端: koa2 + mysql + sequelize

部署:server端 运行在 3000 端口,前端 80 端口,nginx设置代理

喜欢或对你有帮助,欢迎 star

功能

[x] 登录

[x] 分页

[x] 查询

[x] 标签列表

[x] 分类列表

[x] 收藏列表

[x] 文章列表

[x] 发布文章时间轴

[x] 文章访问次数统计

[x] 回到顶部

[x] 博客适配移动端

[ ] 后台适配移动端

[ ] 对文章访问次数进行可视化

[ ] 留言评论

[ ] 渲染优化、打包优化

效果

标签

756cb3d3101ff8b1ff7e60f0f5012496.png

分类

e577e8919304e71a3742401941ff000d.png

收藏

26dc07bf1ed7a83acc6c0c7c5dce120a.png

文章

e53a6386160216090d309e1eb943fc20.png

编辑

18199c4c65cef278af4403aad31ba7a0.png

博客页

e3477da474ca08ff5d383c3fbe3d67f6.png

响应式

33a84ae0b57f53c81c2b6019ff976cfa.png

f180c2a6f4628128cf89d7d5b4bf833d.png

运行项目

前端

git clone https://github.com/gzwgq222/blog-admin.git

cd blog-admin

npm install

localhost:2019

server 端

本地安装 mysql,新建 dev 数据库

git clone https://github.com/gzwgq222/blog-server.git

cd blog-server

npm install

server 端

前端 react + antd 开发,较为平缓,在此就不再叙述。主要记录下 koa + mysql 相关事宜

全局安装 koa-generator

npm install -g koa-generato

创建 node-server 项目

koa node-server

安装依赖

cd node-server

npn install

运行

npm dev

出现 Hello Koa 2! 表示运行成功

fb378b94eda87363efa07c74868bd7fa.png

先看routes文件

index.js

const router = require('koa-router')()

router.get('/', async (ctx, next) => {

await ctx.render('index', {

title: 'Hello Koa 2!'

})

})

router.get('/string', async (ctx, next) => {

ctx.body = 'koa2 string'

})

router.get('/json', async (ctx, next) => {

ctx.body = {

title: 'koa2 json'

}

})

module.exports = router

users.js

const router = require('koa-router')()

router.prefix('/users')

router.get('/', function (ctx, next) {

ctx.body = 'this is a users response!'

})

router.get('/bar', function (ctx, next) {

ctx.body = 'this is a users/bar response'

})

module.exports = router

分别访问下列路由

localhost:3000/string

localhost:3000/users

localhost:3000/bar

大概你已经猜到了,koa-router 定义路由访问时返回相应的内容,那我们只需要把相应的 data 返回去就行了,只是我们的数据得从数据库查询出来。

本地安装 mysql

项目安裝 mysql

npm install mysql --save

项目安裝 sequelize

sequelize 是 ORM node框架,对SQL查询语句的封装,让我们可以用OOP的方式操作数据库

npm install --save sequelize

新建 sequelize.js,建立连接池

const Sequelize = require('sequelize');

const sequelize = new Sequelize('dev', 'root', '123456', {

host: 'localhost',

dialect: 'mysql',

operatorsAliases: false,

pool: {

max: 5,

min: 0,

acquire: 30000,

idle: 10000

}

})

sequelize

.authenticate()

.then(() => {

console.log('MYSQL 连接成功......');

})

.catch(err => {

console.error('链接失败:', err);

});

// 根据模型自动创建表

sequelize.sync()

module.exports = sequelize

创建 model、controllers 文件夹 定义model:定义表结构;controller:定义对数据库的查询方法

6e1e1a8a3251f08b8d876621ae97c49d.png

以 tag.js 为例

model => tag.js

const sequelize = require('../sequelize ')

const Sequelize = require('sequelize')

const moment = require('moment') // 日期处理库

// 定义表结构

const tag = sequelize.define('tag', {

id: {

type: Sequelize.INTEGER(11), // 设置字段类型

primaryKey: true, // 设置为主建

autoIncrement: true // 自增

},

name: {

type: Sequelize.STRING,

unique: { // 唯一

msg: '已添加'

}

},

createdAt: {

type: Sequelize.DATE,

defaultValue: Sequelize.NOW,

get() {

// this.getDataValue 获取当前字段value

return moment(this.getDataValue('createdAt')).format('YYYY-MM-DD HH:mm')

}

},

updatedAt: {

type: Sequelize.DATE,

defaultValue: Sequelize.NOW,

get() {

return moment(this.getDataValue('updatedAt')).format('YYYY-MM-DD HH:mm')

}

}

},

{

// sequelize会自动使用传入的模型名(define的第一个参数)的复数做为表名 设置true取消默认设置

freezeTableName: true

})

module.exports = tag

controller => tag.s 定义了 create、findAll、findAndCountAll、destroy 方法

const Tag = require('../model/tag')

const Op = require('sequelize').Op

const listAll = async (ctx) => {

const data = await Tag.findAll()

ctx.body = {

code: 1000,

data

}

}

const list = async (ctx) => {

const query = ctx.query

const where = {

name: {

[Op.like]: `%${query.name}%`

}

}

const {rows:data, count: total } = await Tag.findAndCountAll({

where,

offset: (+query.pageNo - 1) * +query.pageSize,

limit: +query.pageSize,

order: [

['createdAt', 'DESC']

]

})

ctx.body = {

data,

total,

code: 1000,

desc: 'success'

}

}

const create = async (ctx) => {

const params = ctx.request.body

if (!params.name) {

ctx.body = {

code: 1003,

desc: '标签不能为空'

}

return false

}

try {

await Tag.create(params)

ctx.body = {

code: 1000,

data: '创建成功'

}

}

catch(err) {

const msg = err.errors[0]

ctx.body = {

code: 300,

data: msg.value + msg.message

}

}

}

const destroy = async ctx => {

await Tag.destroy({where: ctx.request.body})

ctx.body = {

code: 1000,

desc: '删除成功'

}

}

module.exports = {

list,

create,

listAll,

destroy

在 routers 文件夹 index.js 中引入定义好的 tag controller ,定义路由

const router = require('koa-router')()

const Tag = require('../controllers/tag')

// tag

router.get('/tag/list', Tag.list)

router.get('/tag/list/all', Tag.listAll)

router.post('/tag/create', Tag.create)

router.post('/tag/destroy', Tag.destroy)

module.exports = router

/* 如每个 route 是单独的文件,可以使用 router.prefix 定义路由前缀

router.prefix('/tag')

router.get('/list', Tag.list)

router.get('/list/all', Tag.listAll)

router.post('/create', Tag.create)

router.post('/destroy', Tag.destroy)

*/

因为 app 中 已经引入 routers 中的 index.js 调用了 app.use了,所以此处不需再引入

在浏览器里输入 localhost:3000/tag/list 就可以看到返回的数据结构了,只不过 data 为空数组,因为我们还没添加进去任何数据

到这里,model 定义表结构、sequelize操作数据库、koa-router 定义路由 这一套流程算是完成了,其他表结构,接口 都是一样定义的

总结

之前没有写过 node server 和 react,算是从零搭建该博客,踩了一些坑,也学到了很多东西,譬如react 开发模式、react-router、sequelize 操作mysql的crud、koa、nginx的配置等等。

麻雀虽小,也是一次完整的前后端开发体验,脱离了浏览器的限制,像海贼王一样,打开了新世界的大门,寻找 onepiece ......

后续会在个人博客中添加关于此次部署文章

Links

初尝 react + Node,错误之处还望斧正,欢迎提 issue

内容来源于网络如有侵权请私信删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值