Date: 2020-4-23

以前很少写文章,从今天开始我要挑战一下自己,连续输出100篇技术类文章。这100篇文章我尽量以实战案例为主。

如果你觉得本文还不错,记得关注或者给个 star,你们的赞和 star 是我编写更多更精彩文章的动力!

GitHub 地址

本文重点内容

  • 从 0 到 1 集成 node + mysql + ejs 用户管理系统
  • 上手 sequelize 不使用sql操作数据库
  • 熟悉 MVC 开发模式

成品演示

关键技术点

  • 1.1 数据库操作
  • 1.2 MVC 模式是什么?

1.1 数据库操作

// 使用 sequelize 代理数据库操作
const { Sequelize, Model, DataTypes } = require('sequelize');
const config = require('./config') // 配置数据库连接
const sequelise = new Sequelize(
dbName,
username, password,
{
host: host,
dialect: 'mysql', // 配置方言
})
class User extends Model {} // 创建表
User.init({
username: DataTypes.STRING,
birthday: DataTypes.DATE
}, { sequelize, modelName: 'user' }); sequelize.sync() // 生成数据表
.then(() => User.create({ // 插入数据
username: 'janedoe',
birthday: new Date(1980, 6, 20)
}))
.then(jane => {
console.log(jane.toJSON());
});

1.2 MVC模式是什么?

MVC即Model、View、Controller即模型、视图、控制器

Module     - 对象和业务逻辑
View - 用户界面
Controller - 用来调度 View 和 Model

开始撸代码

第一步 初始化目录

先来初始化下目录结构:

$ mkdir demo_001 && cd demo_001
$ npm init -y
$ npm i -s nodemon better-npm-run
$ npm i -s koa koa-views @koa/router koa-bodyparser
$ npm i -s ejs sequelize mysql2

各个库的版本号为:

@koa/router: 9.0.0, better-npm-run: 0.1.1,ejs: 3.0.2,koa: 2.11.0,koa-views:6.2.1,sequelize:5.21.6,koa-bodyparser:4.3.0,koa-static:5.0.0,mysql2:2.1.0,nodemon:2.0.3

添加 npm scripts 到 package.json:

    "scripts": {
"start": "npm run dev",
"dev": "better-npm-run dev",
"prd": "better-npm-run prd"
},
"betterScripts": {
"dev": {
"command": "nodemon app.js",
"env": {
"NODE_ENV": "development"
}
},
"prd": {
"env": {
"NODE_ENV": "production"
},
"command": "pm2 start app.js -n demo_001"
}
},

第二步 实现 view 层

新建 app.js

// app.js 代码
const Koa = require('koa');
const views = require('koa-views');
const path = require('path');
const bodyparser = require('koa-bodyparser'); const app = new Koa(); app.keys = ['my keys']; app.use(bodyparser());
app.use(views(path.join(__dirname, './views'), { extension: 'ejs' })); app.listen(3000, () => {
console.log('server is running', new Date());
});

让代码跑起来,之后修改代码不用频繁的重启服务。因为开发环境是用 nodemon 托管的

$ npm start

新建 views 目录结构

  demo_001
├── router
│ └── index.js
├── views
│ ├── index.ejs
│ ├── header.ejs
│ ├── create.ejs
│ └── edit.ejs
└── app.json
└── package.json

view 层核心代码:

<!-- views/header.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>node + mysql 实现增删改查</title>
</head>
<body>
<!-- views/index.ejs -->
<% include('./header.ejs') %>
<h1>
<%= title %>
<small>实现增删改查</small>
</h1>
<a href="/user/create">添加用户</a>
<style>
table{
border-color: #ccc;
}
table td, th{
background: #fff;
}
</style>
<table cellspacing="1" cellpadding="15" bgcolor="#000" >
<thead>
<tr>
<th>username</th>
<th>pwd</th>
<th>phone</th>
<th>age</th>
<th>gender</th>
<th>操作</th>
</tr>
</thead>
<% for (const user of users) { %>
<tr>
<td><%= user.username %></td>
<td><%= user.pwd %></td>
<td><%= user.phone %></td>
<td><%= user.age %></td>
<td><%= user.gender %></td>
<td>
<a href="/user/edit?id=<%= user.id %>">修改</a>
<a href="/user/del/<%= user.id %>">删除</a>
</td>
</tr>
<% } %>
</table>
</body>
</html>
<!-- views/create.ejs -->
<% include('./header.ejs') %>
<style>
label{
width: 80px;
display: inline-block;
text-align: right;
padding-right: 10px;
}
</style>
<h1>
<%= title %> <small><a href="/">返回首页</a></small>
</h1>
<form action="/user/create" method="POST" >
<fieldset>
<label>username</label>
<input value="" name="username" />
</fieldset>
<fieldset>
<label>pwd</label>
<input value="" name="pwd" />
</fieldset>
<fieldset>
<label>phone</label>
<input value="" name="phone" />
</fieldset>
<fieldset>
<label>age</label>
<input value="" name="age" />
</fieldset>
<fieldset>
<label>gender</label>
<input value="" name="gender" />
</fieldset>
<fieldset>
<button type="submit">Submit</button>
</fieldset>
</form>
</body>
</html>
<!-- views/edit.ejs -->
<% include('./header.ejs') %>
<style>
label{
width: 80px;
display: inline-block;
text-align: right;
padding-right: 10px;
}
</style>
<h1>
<%= title %> <small><a href="/">返回首页</a></small>
</h1>
<form action="/user/edit" method="POST" >
<input value="<%= user.id %>" name="id" type="hidden" />
<fieldset>
<label>username</label>
<input value="<%= user.username %>" name="username" />
</fieldset>
<fieldset>
<label>pwd</label>
<input value="<%= user.pwd %>" name="pwd" />
</fieldset>
<fieldset>
<label>phone</label>
<input value="<%= user.phone %>" name="phone" />
</fieldset>
<fieldset>
<label>age</label>
<input value="<%= user.age %>" name="age" />
</fieldset>
<fieldset>
<label>gender</label>
<input value="<%= user.gender %>" name="gender" />
</fieldset>
<fieldset>
<button type="submit">Submit</button>
</fieldset>
</form>
</body>
</html>

路由部分核心代码:

const Router = require('@koa/router');
const router = new Router() // 首页,查询所有用户
router.get('/', async ctx => {
let users = []
console.log('查询所有用户')
await ctx.render('index', { title: 'node + mysql ', users });
});
// 增加
router.get('/user/create', async ctx => {
await ctx.render('create', { title: '添加用户', method: 'add' })
})
router.post('/user/create', async ctx => {
console.log('添加用户:',ctx.request)
ctx.redirect('/')
})
// 修改
router.get('/user/edit', async ctx => {
const codition = { id: ctx.query.id }
console.log('查询要修改的用户',codition)
await ctx.render('edit', { title: '修改用户', method: 'edit', user: {} })
})
router.get('/user/edit', async ctx => {
console.log('要修改的用户:', ctx.request)
ctx.redirect('/')
})
// 删除
router.get('/user/del/:id', async ctx => {
console.log('删除用户id,', ctx.params.id)
ctx.redirect('/')
}) module.exports = router;

目前为止所有的路由已经准备好了,需要挂载到 koa 实例上

// 修改 app.js
// 引入路由部分
const indexRouter = require('./router/index')
// 挂载到 koa 实例
app.use(indexRouter.routes(), indexRouter.allowedMethods());

到这一步我们已经把页面做好了

打开浏览器输入 http://localhost:3000

到此为止,页面已经可以访问了



第三步 实现 module 层

新建 module 目录结构

  demo_001
├── config
│ ├── dev.js
│ ├── prd.js
│ └── index.js
├── modules
│ └── user.js
├── router
├── views
├── db.js
├── app.json
└── package.json

我们先要配置数据库连接:

// config/index.js
if (process.env.NODE_ENV === 'production') {
module.exports = require('./prd')
} else {
module.exports = require('./dev')
}

dev 和 prd 分别对应不同环境的数据库连接。这里都写成你自己的数据库地址即可

// config/prd.js, config/dev.js
module.exports = {
db: {
// host
host: '127.0.0.1',
// 数据库名
dbName: 'xxxx',
// 用户名
username: 'xxxx',
// 密码
password: 'xxxx'
}
}

连接数据库 db.js

// db.js
const Sequelize = require('sequelize');
const config = require('./config') const { dbName, username, password, host } = config.db; const sequelise = new Sequelize(
dbName,
username, password,
{
host: host,
dialect: 'mysql',
// 配置连接池
pool: {
max: 5,
min: 0,
acquire: 30000,
idle: 10000
}
}) sequelise
.authenticate()
.then(() => {
console.log('数据库连接成功')
})
.catch(err => {
throw new Error('数据库连接失败', err)
}) module.exports = sequelise

创建 module

// modules/user.js
const Sequelize = require('sequelize') const sequelize = require('../db'); const User = sequelize.define('user', {
username: { type: Sequelize.STRING },
pwd: { type: Sequelize.STRING, },
phone: { type: Sequelize.STRING, },
age: { type: Sequelize.STRING, },
gender: { type: Sequelize.INTEGER, },
}); module.exports.add = async (data) => await User.create(data)
module.exports.del = async (id) => await User.destroy({ where: { id } }) module.exports.update = async (data) => {
let newUser = {...data}
delete newUser['id']
return await User.update({ ...newUser }, {
where: { id: data.id }
})
} module.exports.find = async (condition) => {
if (Object.keys(condition).length) {
return await User.findAll({ where: { ...condition } })
} else {
return await User.findAll();
}
}

第四步 控制层调度

现在要通 修改 过路由,把视图和 module 结合起来。

// router/index.js
// 引入
const UserMudule = require('../modules/user') // 修改路由:增加
router.post('/user/create', async (ctx) => {
const {
username, pwd, phone, age, gender
} = ctx.request.body
await UserMudule.add({
username, pwd, phone, age, gender
})
ctx.redirect('/')
})
// 修改路由:首页,查询所有用户
router.get('/', async ctx => {
let users = await UserMudule.find(ctx.query)
await ctx.render('index', { title: 'node + mysql ', users });
});
此时已经实现了增加和查询,你可以测试一下这部分功能。

接下来实现修改和删除的代码

// router/index.js
// 修改路由:delete
router.get('/user/del/:id', async ctx => {
await UserMudule.del(ctx.params.id)
ctx.redirect('/')
}) // 修改路由:update
router.get('/user/edit', async ctx => {
const codition = { id: ctx.query.id }
// 修改前先查询出 User 对象
let user = await UserMudule.find(codition)
await ctx.render('edit', { title: '修改用户', method: 'edit', user: user[0] })
}) // 修改路由:update
router.post('/user/edit', async ctx => {
const {
username, pwd, phone, age, gender, id
} = ctx.request.body
// 接受参数,执行修改
await UserMudule.update({
id, username, pwd, phone, age, gender
})
ctx.redirect('/')
})

来,测试一下!

总结

到此你已经掌握了简单的 nodejs 服务器开发,下一篇文章我继续带你一步步的上线一个 nodejs 项目

所以,如果你看完真觉得不错,那就给个 star 吧!你的赞和 star 是我编写更多精彩文章的动力GitHub 地址

后记

这篇文章我花了6个小时,写代码,录gif 脖子和胳膊都酸了~~

希望小伙伴们给我一点点打赏,鼓励我写成更多干货文章



koa+mysql实现增删改查-全栈之路(001)的更多相关文章

  1. Java连接MySQL数据库增删改查通用方法

    版权声明:本文为博主原创文章,未经博主允许不得转载. Java连接MySQL数据库增删改查通用方法 运行环境:eclipse+MySQL 以前我们Java连接MySQL数据库都是一个数据库写一个类,类 ...

  2. MySQL数据库(增删改查语句)

    MySQL数据库(增删改查语句)一.登录数据库:---->  mysql -uroot -proot;(对应用户名和密码)二.SQL语句:    数据定义语言DDL  用来定义数据库.表.列,关 ...

  3. python操作mysql数据库增删改查的dbutils实例

    python操作mysql数据库增删改查的dbutils实例 # 数据库配置文件 # cat gconf.py #encoding=utf-8 import json # json里面的字典不能用单引 ...

  4. Asp.Net操作MySql数据库增删改查

    Asp.Net操作MySql数据库增删改查,话不多说直接步入正题.git源码地址:https://git.oschina.net/gxiaopan/NetMySql.git  1.安装MySQL数据库 ...

  5. Mysql 的 增删改查

    mysql的增删改查 1:新建数据库 create database 数据库名 [其他选项]; 2:新建数据表 create table students ( id int unsigned not ...

  6. MySQL之增删改查之

    MySQL之增删改查   前言:以下是MySQL最基本的增删改查语句,很多IT工作者都必须要会的命令,也是IT行业面试最常考的知识点,由于是入门级基础命令,所有所有操作都建立在单表上,未涉及多表操作. ...

  7. MySql之增删改查 · YbWork's Studio

    前提:在进行"增删改查"的操作之前,先建立一个包含数据表student的数据库(具体操作可以见MySQL之最基本命令): 1."增"--添加数据 1.1 为表中 ...

  8. 使用MySQL练习增删改查时因为版本问题出现连接错误

    使用MySQL练习增删改查时出现连接错误,错误提示如下: 2020-02-19 19:53:51.088 ERROR 16328 --- [reate-249798694] com.alibaba.d ...

  9. (转)mysql的增删改查

    MySQL数据库的增删改查. 1,首先启动mysql数据库的服务,在运行的窗口中输入:net start mysql,这样,就可 以启动mysql数据库的服务,同理,输入net stop mysql, ...

随机推荐

  1. .Net Core 跨平台开发实战-服务器缓存:本地缓存、分布式缓存、自定义缓存

    .Net Core 跨平台开发实战-服务器缓存:本地缓存.分布式缓存.自定义缓存 1.概述 系统性能优化的第一步就是使用缓存!什么是缓存?缓存是一种效果,就是把数据结果存在某个介质中,下次直接重用.根 ...

  2. 求组合数m_n

    下面为求取组合数的代码: #include <stdio.h> #define MAX 10009 ]; void print(int *v, int length) { ; for (; ...

  3. Vim查找与替换命令大全,功能完爆IDE!

    Vi/Vim 可以说是文本编辑中的一代传奇人物,直至现在,它仍然在高级程序员的武器库中占有一席之地.每个 Linux 发行版默认都包含Vim ,而且即使你不是 Linux 系统用户,你也可以安装 Vi ...

  4. thinkphp后端开发ajax接口开发测试

    数据自动填充,Firefox的网络查看JSON数据,查错. 同时,用getLastSql函数查询,并且开启日志文件记录网页执行的全过程,还可以用thinkPHP内置的trace的跟踪. 谁有更好地方法 ...

  5. 鬼吹灯之龙岭迷窟百度云迅雷BT在线观看免费全集

    看视频搜索微信公众号:qyw1091 还记得去年5月11日在高家堡举行的<鬼吹灯之龙岭迷窟>开机仪式吗?时隔数月,这部网剧于4月1日将在腾讯视频全网独播了! . <鬼吹灯之龙岭迷窟& ...

  6. docker win10 基本指令

    一.镜像操作 docker images 本地镜像 docker pull imagename 获取网上获取镜像 docker run 创建docker容器 docker rmi imagename ...

  7. javascript入门 之 ztree (八 一系列鼠标事件)

    <!DOCTYPE html> <HTML> <HEAD> <meta http-equiv="content-type" content ...

  8. 白话说编程之java线程

    线程和进程: 在说多线程之前,我们先来研究一下线程,说到线程,我们又不得不说到进程,因为很多初学者会把线程和进程分不清,搞混淆. 进程: 是操作系统系统运行的最小单元.怎么理解这句话,可以这样去对比, ...

  9. 37.2 net-- tcp传输 ServerSocket、Socket

    一.打开server端 package day35_net_网络编程.tcp传输; import java.io.IOException; import java.io.InputStream; im ...

  10. python调用js

    安装 pip install PyExecJS 方法 eval() 输入参数:source(JS语句).cwd(路径) 返回值:result(语句执行结果) compile() 输入参数:source ...