前言:现在前端主要使用vue和react做spa单页面应用,但有美中不足。ssr服务器渲染也是一个潮流。空余时间自己用node+mysql做个demo例子,主要是学会如何工作的。
技术:node(前端)+mysql(数据库)
我们可以用脚手架创建一个项目,这里就不多说了,不会去百度。
下面就是一个基础目录
我创建的是react,因为这次没有用到react,所有我们所有操作都在server文件夹下
创建一个server文件夹,先安装koa,node创建服务器很简单。
1.我们在app.js写代码,打开浏览器运行成功
const Koa = require('koa') //引用koa
const app = new Koa()
app.listen(4000, () => {
console.log('4000端口启动了')
})
2.接下来我们配置mysql,还是先安装mysql,然后早config文件夹创建config.js配置我们的服务器
const config = {
// 数据库配置
database: {
DATABASE: '', // 数据库名称
USERNAME: ' ', // mysql用户名
PASSWORD: ' ', // mysql密码
PORT: ' ', // mysql端口号
HOST: ' ' // 服务器ip
}
}
module.exports = config
写上自己的服务器信息就可以了。
3.接下来我们写接口了,在api文件夹下创建一个testone.js
const mysql = require('mysql'); 引入mysql
const config = require('../config/config'); //引入刚才配置的服务器信息
const pool = mysql.createPool({
host: config.database.HOST,
user: config.database.USERNAME,
password: config.database.PASSWORD,
database: config.database.DATABASE
});
//下面是一个promise对象
const allServices = {
query: function (sql, values) {
return new Promise((resolve, reject) => {
pool.getConnection(function (err, connection) {
if (err) {
reject(err)
} else {
connection.query(sql, values, (err, rows) => {
if (err) {
reject(err)
} else {
resolve(rows)
}
connection.release()
})
}
})
})
},
//查询数据库表格所有对象
findUserData: (name) => {
const _sql = 'select * from test1modal;'
return allServices.query(_sql)
},
//添加数据
addUserData: (obj) => {
const _sql = 'insert into test1modal(idd,nickname) value (?,?)'
console.log('a', _sql)
return allServices.query(_sql, obj)
}
}
module.exports = allServices;
4.下面我们就需要写操作了在option文件下创建user.js。因为我们需要用到路由了所有我们需要安装koa-router。fs,path一般安装node都自动安装上,如果没有那需要你手动安装。
因为我用的是html。在代码里可以看到当我们访问/test,他会加载public下的index.html页面。我们需要设置加载的type是html,用path.join(_dirname,../pulice/idex.html)拼接起来,让服务器知道我们要访问public下的index.html页面了。
const Router = require('koa-router')
const router = new Router()
const userService = require('../api/testone.js');
const fs = require('fs');
const path = require('path')
// koa-static连接资源
router.get('/test', async (ctx, next) => {
ctx.response.type = 'html';
ctx.response.body = fs.createReadStream(path.join(__dirname, '../public/index.html'));
})
// 获取所有用户(GET请求)
router.get('/list', async (ctx, next) => {
console.log('userService', userService.findUserData())
const info = await userService.findUserData();
ctx.body = ({
meg: '查询成功',
code: '10000',
data: info
})
})
// 增加用户(POST请求)
router.post('/add', async (ctx, next) => {
const arr = []
arr.push(ctx.request.body.idd)
arr.push(ctx.request.body.name)
await userService.addUserData(arr)
.then((data) => {
let r = '';
if (data.affectedRows !== 0) {
r = '添加成功';
}
ctx.body = {
data: r
}
}).catch(() => {
ctx.body = {
data: '添加失败'
}
})
})
module.exports = router
5.接口写好了,接下来我们写public文件夹创建index.html
我用的是react,你也可以用vue或者原生的html写法,都是大同小异。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
<title>node</title>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
//主要内容
class Main extends React.Component {
//
test() {
let id = document.getElementById('btn')
var name = document.getElementById("idd").value;
let param = {
idd: document.getElementById("idd").value,
name: document.getElementById("name").value
}
id.onclick = function (e) {
axios.post('/add', param)
.then(res => {
// 接口数据
console.log(res.data)
})
}
}
render = () => {
return (
<div>
<Addinfo></Addinfo>
<ListInfo></ListInfo>
</div>
)
}
}
//添加信息
class Addinfo extends React.Component {
test() {
let id = document.getElementById('btn')
var name = document.getElementById("idd").value;
let param = {
idd: document.getElementById("idd").value,
name: document.getElementById("name").value
}
id.onclick = function (e) {
axios.post('/add', param)
.then(res => {
// 接口数据
console.log(res.data)
})
}
}
render = () => {
return (
<div>
<input type="text" id='idd' placeholder="请输入id" />
<input type="text" id='name' placeholder="请输入名称" />
<button id='btn' onClick={() => { this.test() }}>点击添加</button>
</div>
)
}
}
//列表信息
class ListInfo extends React.Component {
state = {
list: []
}
componentDidMount() {
axios.get('/list').then(res => {
console.log('res', res)
if (res.data && res.data.code === '10000') {
this.setState({
list: res.data.data
})
}
})
}
render = () => {
return (
<div>
{
this.state.list && this.state.list.length > 0
? <div>
<ul>
{
this.state.list.map((item, i) => (
<li key={i}>{item.nickname}</li>
))
}
</ul>
</div> : 'null'
}
</div>
)
}
}
ReactDOM.render(<Main />,
document.getElementById('app'),
)
</script>
</body>
</html>
6.准备工作写完了,我们要开始写入口文件了app.js
我在这里设置了跨域用到了koa2-cors
还配置了静态资源拼接用到了koa-static
app.use(serve(path.join(__dirname, '/server/public/')));// 静态资源拼接
在弟4步中,我们访问/test,会加载index.html页面,如果不配置,会找不到
这里还用到了koa-bodyparser
利用koa-bodyparser来处理POST请求参数,
在第4步中我们添加数据用的post请求,boby传有参数,koa-bodyparser就是用到回去body的参数。需要注意的是const bodyparser = new BodyParser(); bodyparser必须在路由加载前使用,不然无效。
const Koa = require('koa')
const Router = require('./option/user.js')
const app = new Koa()
const serve = require('koa-static')
const path = require('path')
const cors = require('koa2-cors');
const BodyParser = require('koa-bodyparser');
const bodyparser = new BodyParser();
app.use(cors());
app.use(bodyparser);
// 或者
app.use(
cors({
origin: function (ctx) { // 设置允许来自指定域名请求
// if (ctx.url === '/test') {
// return '*'; // 允许来自所有域名请求
// }
return '*'
// return 'http://localhost:4000'; // 只允许http://localhost:8080这个域名的请求
},
maxAge: 5, // 指定本次预检请求的有效期,单位为秒。
credentials: true, // 是否允许发送Cookie
allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], // 设置所允许的HTTP请求方法
allowHeaders: ['Content-Type', 'Authorization', 'Accept'], // 设置服务器支持的所有头信息字段
exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'] // 设置获取其他自定义字段
})
);
app.use(serve(path.join(__dirname, '/server/public/')));// 静态资源拼接
app.use(Router.routes(), Router.allowedMethods()); // 启动路由
app.listen(4000, () => {
console.log('4000端口启动了')
})
// 错误提示
app.on('error', (err, ctx) => {
console.error('server error', err, ctx)
})
7.我们打开浏览器就可以,前提需要运行app.js 在根目录用node app.js就运行了
我们可以看到获取数据库信息成功。
我们点击添加,可以看到添加成功
我们看下数据库
存在里面了。
基本简单的一个demo就完成了,主要是练习ssr,当然还有许多地方需要完善。