一、express 框架
express是什么?
express是node的一个框架,使用框架可以快速开发服务端程序,处理客户端请求;让后端代码更加清晰
使用 express
1. 安装express
npm install express --save
2. 导入express
let express = require('express');
let bodyParser = require('body-parser');
3. 使用express创建server
let app = express();
4. 使用中间件
app.use(express.static(__dirname)); // 静态资源服务
app.use(bodyParser.json()); // 解析POST请求的数据,并且挂载到req的body上
5 配置路由 (接口)
- get请求
app.get('/login', function (req, res) {
console.log(req.query);
res.send(req.headers);
});
- post请求
app.post('/register', function (req, res) {
console.log(req.body);
res.send({
code: 0,
data: {},
msg: 'ok'
})
});
- 无论get还是post请求都会执行
app.all('/api/xyz', function (req, res) {
console.log('请求来了');
});
5. 监听端口号
app.listen(8000, () => console.log('启动成功'));
二、CRM系统
需求:
- 该系统有一个列表页,列表中每一行是一条数据;该列表需要从服务端动态获取,然后渲染到页面中;
- 在列表上方有一个新增按钮,点击新增跳转到新增页面,在新增页面输入表单中的值,点击保存会自动把数据存到数据库中,如果保存成功则跳回列表页,失败alert提示;
- 在列表中每一行都有一个修改按钮,点击修改跳到修改页面,进入修改页面后要回填原有的数据;点击保存后,把修改后的数据保存到数据库中,如果保存成功则跳转到首页,如果失败则alert提示;
- 列表中每一行有一个删除按钮,点击删除时弹出confirme框,如果点击确定时则删除这条数据,点击取消则不动作;删除成功后刷新列表;
列表首页 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/index.css">
</head>
<body>
<div class="box1">
<a href="/modify.html">增加新客户</a>
<h4 class="head">
<span class="w50">编号</span>
<span class="w150">姓名</span>
<span class="w50">年龄</span>
<span class="w200">电话</span>
<span class="w200">地址</span>
<span class="w150">操作</span>
</h4>
<ul class="list" id="list">
<li>
<span class="w50">1</span>
<span class="w150">2</span>
<span class="w50">3</span>
<span class="w200">电话</span>
<span class="w200">地址</span>
<span class="w150">
<a href="/modify.html">修改</a>
<a href="javascript: void 0;">删除</a>
</span>
</li>
<li>
<span class="w50">1</span>
<span class="w150">2</span>
<span class="w50">3</span>
<span class="w200">电话</span>
<span class="w200">地址</span>
<span class="w150">操作</span>
</li>
<li>
<span class="w50">1</span>
<span class="w150">2</span>
<span class="w50">3</span>
<span class="w200">电话</span>
<span class="w200">地址</span>
<span class="w150">操作</span>
</li>
</ul>
</div>
<script src="/static/js/axios.js"></script>
<script src="/static/js/index.js"></script>
</body>
</html>
新增、修改页面 modify.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="static/css/modify.css">
</head>
<body>
<div class="box2">
<div>
<span>姓名</span>
<input type="text" id="username">
</div>
<div>
<span>年龄</span>
<input type="text" id="age">
</div>
<div>
<span>电话</span>
<input type="text" id="phone">
</div>
<div>
<span>地址</span>
<input type="text" id="address">
</div>
<div class="submit" id="submit">提交</div>
</div>
<script src="/static/js/axios.js"></script>
<script src="/static/js/modify.js"></script>
</body>
</html>
客户端index.js
let list = document.getElementById('list');
function bindHTML(data) {
let str = ``;
data.forEach(({id, name, age, phone, address}) => {
str += `<li>
<span class="w50">${id}</span>
<span class="w150">${name}</span>
<span class="w50">${age}</span>
<span class="w200">${phone}</span>
<span class="w200">${address}</span>
<span class="w150">
<a href="/modify.html?id=${id}">修改</a>
<a href="javascript: void 0;" type="del" data-id="${id}">删除</a>
</span>
</li>`
});
list.innerHTML = str;
}
axios.get('/api/getList').then(({data}) => {
if (data.code === 0) {
bindHTML(data.data)
}
});
list.onclick = function (e) {
if (e.target.nodeName.toUpperCase() === 'A' && e.target.getAttribute('type') === 'del') {
let id = e.target.getAttribute('data-id');
let isDel =confirm(`您要删除id为${id}的用户吗`)
if (isDel) {
axios.get(`/api/removeInfo?id=${id}`).then(({data}) => {
if (data.code === 0) {
window.location.href = '/'
}
})
}
}
};
修改/新增 modify.js
let isModify = /\?id=(\d+)/.exec(location.search);
let $ = selector => document.querySelector(selector);
let submit = $('.submit');
let name = $('#username');
let age = $('#age');
let phone = $('#phone');
let address = $('#address');
// 如果是修改,首先根据id获取数据
if (isModify) {
let [,id] = isModify;
axios.get(`/api/getInfo?id=${id}`).then(({data}) => {
if (data.code === 0) {
name.value = data.data.name;
age.value = data.data.age;
phone.value = data.data.phone;
address.value = data.data.address;
} else {
alert(data.msg)
}
});
}
submit.onclick = function () {
let params = {
name: name.value,
age: age.value,
phone: phone.value,
address: address.value
};
let api = ''
if (isModify) {
let [,id] = isModify;
params.id = +id;
api = '/api/updateInfo'
} else {
api = '/api/addInfo'
}
axios.post(api, params).then(({data}) => {
if (data.code === 0) {
window.location.href = '/'
} else {
alert(data.msg)
}
});
};
服务器端 server.js
let http = require('http');
let fs = require('fs');
let url = require('url');
let mime = require('mime');
let server = http.createServer((req, res) => {
let urlObj = url.parse(req.url, true);
let {pathname, query} = urlObj;
// 静态资源服务
if (pathname === '/' || /(\.\w+)$/.test(pathname)) {
let filePath = '';
let contentType = '';
if (pathname === '/') {
filePath = __dirname + '/index.html';
contentType = 'text/html';
} else {
filePath = __dirname + pathname;
contentType = mime.getType(pathname)
}
fs.readFile(filePath, (err, data) => {
if (err) {
res.statusCode = 404;
res.end(`${pathname} is not found`)
} else {
res.end(data);
}
})
} else {
// 处理ajax接口
res.setHeader('Content-Type', 'application/json;charset=UTF-8;');
let database = __dirname + '/database/custom.json'; // 数据文件路径
let response = {
code: 0,
data: null,
msg: 'ok'
};
// 获取列表
if (pathname === '/api/getList') {
let con = JSON.parse(fs.readFileSync(database, 'utf8'));
response.data = con;
res.end(JSON.stringify(response)); // 服务端不能直接把对象直接响应去,需要对象转成json格式的字符串;
}
// 2. 删除数据
if (pathname === '/api/removeInfo') {
let arr = JSON.parse(fs.readFileSync(database, 'utf8'));
let result = arr.find(item => +item.id === +query.id);
if (result) {
arr = arr.filter(item => +item.id !== +query.id);
fs.writeFileSync(database, JSON.stringify(arr));
res.end(JSON.stringify(response));
} else {
response.code = 1;
response.msg = `id为${query.id}的客户不存在`;
res.end(JSON.stringify(response))
}
}
// 3. 新增客户
if (pathname === '/api/addInfo') {
// 接收客户端post过来的数据
// 如何接收POST的数据呢?
// POST的请求数据量一般比较大,客户端会把数据切段,然后一段一段的传过来,每传过来一次就会触发一次data事件,当最后一段发送完会触发一次end事件
let str = '';
req.on('data', (chunk) => {
// 监听data事件,接收数据
str += chunk;
});
req.on('end', () => {
let curCustom = JSON.parse(str);
// 先读取出来,然后写入;
let con = JSON.parse(fs.readFileSync(database, 'utf8'));
// 为新增的数据生成一个id,如果之前的数据为空,那么这个id为1,如果不为空,那么这个id应该为数据的之前最后一条数据的id + 1
con.length
? curCustom.id = con[con.length - 1].id + 1
: curCustom.id = 1;
con.push(curCustom);
fs.writeFileSync(database, JSON.stringify(con), 'utf8');
res.end(JSON.stringify(response));
})
}
// 4. 获取某个客户的信息
if (pathname === '/api/getInfo') {
// 根据客户端传递的id,从数据库中查出指定id的用户的信息
let con = JSON.parse(fs.readFileSync(database, 'utf8'));
let result = con.find(item => +item.id === +query.id);
if (result) {
response.data = result;
res.end(JSON.stringify(response))
} else {
response.code = 1;
response.msg = `id为${query.id}的用户不存在`;
res.end(JSON.stringify(response))
}
}
// 5. 修改客户信息
if (pathname === '/api/updateInfo') {
let str = '';
req.on('data', (chunk) => str += chunk);
req.on('end', () => {
let curData = JSON.parse(str);
let con = JSON.parse(fs.readFileSync(database, 'utf8'));
let curIndex = con.findIndex(item => +item.id === +curData.id);
console.log(curIndex);
if (curIndex > -1) {
con[curIndex] = curData;
fs.writeFileSync(database, JSON.stringify(con), 'utf8');
res.end(JSON.stringify(response))
} else {
response.code = 1;
response.msg = `id为${curData.id}用户不存在`;
res.end(JSON.stringify(response));
}
})
}
}
});
server.listen(8001, () => console.log('port 8001 is on'));
package.json
{
"name": "crm",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.19.0",
"mime": "^2.4.4"
}
}