一、express 框架

express是什么?

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

使用 express

1. 安装express

  1. 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 配置路由 (接口)

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

5. 监听端口号

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

二、CRM系统

需求:

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

【发上等愿,结中等缘,享下等福,择高处立,寻平处住,向宽处行】