一、express 框架

express是什么?

express是node的一个框架,使用框架可以快速开发服务端程序,处理客户端请求;让后端代码更加清晰

使用 express

1. 安装express

  1. npm install express --save

2. 导入express

  1. let express = require('express');
  2. let bodyParser = require('body-parser');

3. 使用express创建server

  1. let app = express();

4. 使用中间件

  1. app.use(express.static(__dirname)); // 静态资源服务
  2. app.use(bodyParser.json()); // 解析POST请求的数据,并且挂载到req的body上

5 配置路由 (接口)

  1. get请求
  1. app.get('/login', function (req, res) {
  2. console.log(req.query);
  3. res.send(req.headers);
  4. });
  1. post请求
  1. app.post('/register', function (req, res) {
  2. console.log(req.body);
  3. res.send({
  4. code: 0,
  5. data: {},
  6. msg: 'ok'
  7. })
  8. });
  1. 无论get还是post请求都会执行
  1. app.all('/api/xyz', function (req, res) {
  2. console.log('请求来了');
  3. });

5. 监听端口号

  1. app.listen(8000, () => console.log('启动成功'));

二、CRM系统

需求:

  1. 该系统有一个列表页,列表中每一行是一条数据;该列表需要从服务端动态获取,然后渲染到页面中;
  2. 在列表上方有一个新增按钮,点击新增跳转到新增页面,在新增页面输入表单中的值,点击保存会自动把数据存到数据库中,如果保存成功则跳回列表页,失败alert提示;
  3. 在列表中每一行都有一个修改按钮,点击修改跳到修改页面,进入修改页面后要回填原有的数据;点击保存后,把修改后的数据保存到数据库中,如果保存成功则跳转到首页,如果失败则alert提示;
  4. 列表中每一行有一个删除按钮,点击删除时弹出confirme框,如果点击确定时则删除这条数据,点击取消则不动作;删除成功后刷新列表;

列表首页 index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="/static/css/index.css">
  7. </head>
  8. <body>
  9. <div class="box1">
  10. <a href="/modify.html">增加新客户</a>
  11. <h4 class="head">
  12. <span class="w50">编号</span>
  13. <span class="w150">姓名</span>
  14. <span class="w50">年龄</span>
  15. <span class="w200">电话</span>
  16. <span class="w200">地址</span>
  17. <span class="w150">操作</span>
  18. </h4>
  19. <ul class="list" id="list">
  20. <li>
  21. <span class="w50">1</span>
  22. <span class="w150">2</span>
  23. <span class="w50">3</span>
  24. <span class="w200">电话</span>
  25. <span class="w200">地址</span>
  26. <span class="w150">
  27. <a href="/modify.html">修改</a>
  28. <a href="javascript: void 0;">删除</a>
  29. </span>
  30. </li>
  31. <li>
  32. <span class="w50">1</span>
  33. <span class="w150">2</span>
  34. <span class="w50">3</span>
  35. <span class="w200">电话</span>
  36. <span class="w200">地址</span>
  37. <span class="w150">操作</span>
  38. </li>
  39. <li>
  40. <span class="w50">1</span>
  41. <span class="w150">2</span>
  42. <span class="w50">3</span>
  43. <span class="w200">电话</span>
  44. <span class="w200">地址</span>
  45. <span class="w150">操作</span>
  46. </li>
  47. </ul>
  48. </div>
  49. <script src="/static/js/axios.js"></script>
  50. <script src="/static/js/index.js"></script>
  51. </body>
  52. </html>

新增、修改页面 modify.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <link rel="stylesheet" href="static/css/modify.css">
  7. </head>
  8. <body>
  9. <div class="box2">
  10. <div>
  11. <span>姓名</span>
  12. <input type="text" id="username">
  13. </div>
  14. <div>
  15. <span>年龄</span>
  16. <input type="text" id="age">
  17. </div>
  18. <div>
  19. <span>电话</span>
  20. <input type="text" id="phone">
  21. </div>
  22. <div>
  23. <span>地址</span>
  24. <input type="text" id="address">
  25. </div>
  26. <div class="submit" id="submit">提交</div>
  27. </div>
  28. <script src="/static/js/axios.js"></script>
  29. <script src="/static/js/modify.js"></script>
  30. </body>
  31. </html>

客户端index.js

  1. let list = document.getElementById('list');
  2. function bindHTML(data) {
  3. let str = ``;
  4. data.forEach(({id, name, age, phone, address}) => {
  5. str += `<li>
  6. <span class="w50">${id}</span>
  7. <span class="w150">${name}</span>
  8. <span class="w50">${age}</span>
  9. <span class="w200">${phone}</span>
  10. <span class="w200">${address}</span>
  11. <span class="w150">
  12. <a href="/modify.html?id=${id}">修改</a>
  13. <a href="javascript: void 0;" type="del" data-id="${id}">删除</a>
  14. </span>
  15. </li>`
  16. });
  17. list.innerHTML = str;
  18. }
  19. axios.get('/api/getList').then(({data}) => {
  20. if (data.code === 0) {
  21. bindHTML(data.data)
  22. }
  23. });
  24. list.onclick = function (e) {
  25. if (e.target.nodeName.toUpperCase() === 'A' && e.target.getAttribute('type') === 'del') {
  26. let id = e.target.getAttribute('data-id');
  27. let isDel =confirm(`您要删除id${id}的用户吗`)
  28. if (isDel) {
  29. axios.get(`/api/removeInfo?id=${id}`).then(({data}) => {
  30. if (data.code === 0) {
  31. window.location.href = '/'
  32. }
  33. })
  34. }
  35. }
  36. };

修改/新增 modify.js

  1. let isModify = /\?id=(\d+)/.exec(location.search);
  2. let $ = selector => document.querySelector(selector);
  3. let submit = $('.submit');
  4. let name = $('#username');
  5. let age = $('#age');
  6. let phone = $('#phone');
  7. let address = $('#address');
  8. // 如果是修改,首先根据id获取数据
  9. if (isModify) {
  10. let [,id] = isModify;
  11. axios.get(`/api/getInfo?id=${id}`).then(({data}) => {
  12. if (data.code === 0) {
  13. name.value = data.data.name;
  14. age.value = data.data.age;
  15. phone.value = data.data.phone;
  16. address.value = data.data.address;
  17. } else {
  18. alert(data.msg)
  19. }
  20. });
  21. }
  22. submit.onclick = function () {
  23. let params = {
  24. name: name.value,
  25. age: age.value,
  26. phone: phone.value,
  27. address: address.value
  28. };
  29. let api = ''
  30. if (isModify) {
  31. let [,id] = isModify;
  32. params.id = +id;
  33. api = '/api/updateInfo'
  34. } else {
  35. api = '/api/addInfo'
  36. }
  37. axios.post(api, params).then(({data}) => {
  38. if (data.code === 0) {
  39. window.location.href = '/'
  40. } else {
  41. alert(data.msg)
  42. }
  43. });
  44. };

服务器端 server.js

  1. let http = require('http');
  2. let fs = require('fs');
  3. let url = require('url');
  4. let mime = require('mime');
  5. let server = http.createServer((req, res) => {
  6. let urlObj = url.parse(req.url, true);
  7. let {pathname, query} = urlObj;
  8. // 静态资源服务
  9. if (pathname === '/' || /(\.\w+)$/.test(pathname)) {
  10. let filePath = '';
  11. let contentType = '';
  12. if (pathname === '/') {
  13. filePath = __dirname + '/index.html';
  14. contentType = 'text/html';
  15. } else {
  16. filePath = __dirname + pathname;
  17. contentType = mime.getType(pathname)
  18. }
  19. fs.readFile(filePath, (err, data) => {
  20. if (err) {
  21. res.statusCode = 404;
  22. res.end(`${pathname} is not found`)
  23. } else {
  24. res.end(data);
  25. }
  26. })
  27. } else {
  28. // 处理ajax接口
  29. res.setHeader('Content-Type', 'application/json;charset=UTF-8;');
  30. let database = __dirname + '/database/custom.json'; // 数据文件路径
  31. let response = {
  32. code: 0,
  33. data: null,
  34. msg: 'ok'
  35. };
  36. // 获取列表
  37. if (pathname === '/api/getList') {
  38. let con = JSON.parse(fs.readFileSync(database, 'utf8'));
  39. response.data = con;
  40. res.end(JSON.stringify(response)); // 服务端不能直接把对象直接响应去,需要对象转成json格式的字符串;
  41. }
  42. // 2. 删除数据
  43. if (pathname === '/api/removeInfo') {
  44. let arr = JSON.parse(fs.readFileSync(database, 'utf8'));
  45. let result = arr.find(item => +item.id === +query.id);
  46. if (result) {
  47. arr = arr.filter(item => +item.id !== +query.id);
  48. fs.writeFileSync(database, JSON.stringify(arr));
  49. res.end(JSON.stringify(response));
  50. } else {
  51. response.code = 1;
  52. response.msg = `id${query.id}的客户不存在`;
  53. res.end(JSON.stringify(response))
  54. }
  55. }
  56. // 3. 新增客户
  57. if (pathname === '/api/addInfo') {
  58. // 接收客户端post过来的数据
  59. // 如何接收POST的数据呢?
  60. // POST的请求数据量一般比较大,客户端会把数据切段,然后一段一段的传过来,每传过来一次就会触发一次data事件,当最后一段发送完会触发一次end事件
  61. let str = '';
  62. req.on('data', (chunk) => {
  63. // 监听data事件,接收数据
  64. str += chunk;
  65. });
  66. req.on('end', () => {
  67. let curCustom = JSON.parse(str);
  68. // 先读取出来,然后写入;
  69. let con = JSON.parse(fs.readFileSync(database, 'utf8'));
  70. // 为新增的数据生成一个id,如果之前的数据为空,那么这个id为1,如果不为空,那么这个id应该为数据的之前最后一条数据的id + 1
  71. con.length
  72. ? curCustom.id = con[con.length - 1].id + 1
  73. : curCustom.id = 1;
  74. con.push(curCustom);
  75. fs.writeFileSync(database, JSON.stringify(con), 'utf8');
  76. res.end(JSON.stringify(response));
  77. })
  78. }
  79. // 4. 获取某个客户的信息
  80. if (pathname === '/api/getInfo') {
  81. // 根据客户端传递的id,从数据库中查出指定id的用户的信息
  82. let con = JSON.parse(fs.readFileSync(database, 'utf8'));
  83. let result = con.find(item => +item.id === +query.id);
  84. if (result) {
  85. response.data = result;
  86. res.end(JSON.stringify(response))
  87. } else {
  88. response.code = 1;
  89. response.msg = `id${query.id}的用户不存在`;
  90. res.end(JSON.stringify(response))
  91. }
  92. }
  93. // 5. 修改客户信息
  94. if (pathname === '/api/updateInfo') {
  95. let str = '';
  96. req.on('data', (chunk) => str += chunk);
  97. req.on('end', () => {
  98. let curData = JSON.parse(str);
  99. let con = JSON.parse(fs.readFileSync(database, 'utf8'));
  100. let curIndex = con.findIndex(item => +item.id === +curData.id);
  101. console.log(curIndex);
  102. if (curIndex > -1) {
  103. con[curIndex] = curData;
  104. fs.writeFileSync(database, JSON.stringify(con), 'utf8');
  105. res.end(JSON.stringify(response))
  106. } else {
  107. response.code = 1;
  108. response.msg = `id${curData.id}用户不存在`;
  109. res.end(JSON.stringify(response));
  110. }
  111. })
  112. }
  113. }
  114. });
  115. server.listen(8001, () => console.log('port 8001 is on'));

package.json

  1. {
  2. "name": "crm",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "server.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1",
  8. "start": "node server.js"
  9. },
  10. "author": "",
  11. "license": "ISC",
  12. "dependencies": {
  13. "axios": "^0.19.0",
  14. "mime": "^2.4.4"
  15. }
  16. }