zoukankan      html  css  js  c++  java
  • node.js入门学习(四)--Demo图书的增删改查

    需求:图书的增删改查,图书数据保存在data.json文件中。

    1、Demo结构:

      

    2、首先下载安装node.js,配置环境变量:参考博客

    3、项目初始化

      1)创建项目根目录node-hello,进入到根目录node-hello,右键/在此处打开PowerShell窗口。

      2)创建app.js文件。

      3)在控制台输入命令:npm init -y,会自动创建package.json文件。

      4)在控制台输入命令:npm install mime,会自动创建node_modules文件夹,并下载mime模块到该文件夹,还会自动生成package-lock.json文件。

      5)npm install underscore,下载underscore模块。underscore的使用参考博客

    4、入口文件app.js

    // 加载http模块
    var http = require("http");
    var fs = require("fs");
    var path = require("path");
    var mime = require("mime");
    var url = require("url");
    var querystring = require("querystring");
    var _ = require("underscore");
    
    // 创建一个http服务对象
    http.createServer(function(req, res) {
    
        req.url = req.url.toLowerCase();
        req.method = req.method.toLowerCase();
        if (req.method === 'get') { 
            // 通过url模块的parse方法获取用户get请求提交的数据
            // 第二个参数为true时,urlObj的query属性就是所有的请求参数,类型是json对象
            var urlObj = url.parse(req.url, true);
            // console.log(urlObj);
        } 
    
        // 封装fender函数,将render函数挂在到res对象上;第二个参数是模板数据
        res.render = function (filename, templateData) {
            fs.readFile(filename, function(err, data) {
                if(err) {
                    res.writeHead(404, 'not found', {'Content-Type': 'text/html; charset=utf-8'});
                    res.end("404, not found.");
                    return;
                }
    
                if (templateData) {
                    var fn = _.template(data.toString("utf-8"));
                    data = fn(templateData);
                }
                
                res.setHeader('Content-Type', mime.getType(filename));
                res.end(data);
            });
        };
    
        if(req.url === '/' || req.url === '/index') {
            res.render(path.join(__dirname, 'pages/index.html'));
        } 
        else if(req.url === '/list') {
            // 第一步:读取data.json文件中的数据,转换为list数组
            fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function (err, data) {
                if(err && err.code !== 'ENOENT') {throw err;}
                console.log("data.json原来的内容:" + data); // [{"name":"xxx","price":"xxx"}]]
                var bookList = JSON.parse(data || '[]'); // json数组
    
                // 第二步:在服务器使用模版引擎,将bookList数据和list.html页面结合
                res.render(path.join(__dirname, 'pages/list.html'), {msg:'这是list页面', bookList:bookList});
            });
        } 
        else if(req.url.startsWith('/add')) {
            res.render(path.join(__dirname, 'pages/add.html'));
        } 
        else if(req.url.startsWith('/submit') && req.method === 'get') { // 如何获取get请求的参数
            // 用户表单提交get请求数据,保存到data/data.json文件中,新数据以追加的形式添加
            console.log(req.url); // /summit?name=xxx&price=xxx
    
            // 首先读取data.json文件的内容
            fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function (err, data) {
                if(err && err.code !== 'ENOENT') {throw err;}
                console.log("data.json原来的内容:" + data); // [{"name":"xxx","price":"xxx"}]]
                var list = JSON.parse(data || '[]'); // json数组
    
                // 获取get请求的参数,将用户提交的数据添加到json数组
                var book = urlObj.query;
                // book.id = list.length + 1;
                book.id = list[list.length - 1].id + 1;
                list.push(book);
                console.log("添加一条记录后,data.json的内容:"  + JSON.stringify(list));
                
                // 将json数组写入data.json文件
                fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(list), function(err) {
                    if(err) throw err;
                    console.log('写入成功');
                });    
            });
    
            // 重定向
            res.statusCode = 302;
            res.statusMessage = 'Found';
            res.setHeader('Location', '/index');
            res.end();
        } 
        else if(req.url.startsWith('/submit') && req.method === 'post') { // 如何获取post请求的参数
            var array = []; // 用来保存用户post请求提交的数据
            var postBody;
            req.on('data', function(chunk) {
                // chunk就是浏览器本次data事件提交的一部分数据;chunk是Buffer类型
                console.log("data事件...");
                array.push(chunk);
            });
    
            req.on('end', function() {
                console.log("end事件...");
                // 把array中多个Buffer对象汇总到一个Buffer对象
                postBody = Buffer.concat(array);
                console.log("postBody: " + postBody); // postBody: name=1&price=1
            });
    
            fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function (err, data) {
                if(err && err.code !== 'ENOENT') {throw err;}
                console.log("data.json原来的内容:" + data); // [{"name":"xxx","price":"xxx"}]]
                var list = JSON.parse(data || '[]'); // json数组
    
                // 获取get请求的参数,将用户提交的数据添加到json数组
                // querystring对象可以把表单数据 name=xxx&price=xxx => {"name":"xxx","price":"xxx"}
                var book = querystring.parse(postBody.toString("utf-8"));
                // book.id = list.length + 1;
                book.id = list[list.length - 1].id + 1;
                list.push(book);
                console.log("添加一条记录后,data.json的内容:"  + JSON.stringify(list));
                
                // 将json数组写入data.json文件
                fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(list), function(err) {
                    if(err) throw err;
                    console.log('写入成功');
                });    
            });
    
            /*
            // 首先读取data.json文件的内容
            fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function (err, data) {
                if(err && err.code !== 'ENOENT') {throw err;}
                console.log("data.json原来的内容:" + data); // [{"name":"xxx","price":"xxx"}]]
                var list = JSON.parse(data || '[]'); // json数组
    
                // 获取post请求的参数,将用户提交的数据添加到json数组
                // 因为post提交数据的时候,数据量可能比较大,所以可能分多次提交,每次添加一部分数据
                // 此时服务器要获取用户提交的所有数据,必须监听request对象的data事件
                // 什么时候表示浏览器把所有数据都提交到服务器了呢?当request对象的end事件触发
                var array = []; // 用来保存用户post请求提交的数据
                console.log("111...");
                req.on('data', function(chunk) {
                    // chunk就是浏览器本次data事件提交的一部分数据;chunk是Buffer类型
                    console.log("data事件...");
                    array.push(chunk);
                });
                req.on('end', function() {
                    console.log("end事件...");
                    // 把array中多个Buffer对象汇总到一个Buffer对象
                    var postBody = Buffer.concat(array);
                    console.log("postBody: " + postBody);
                    list.push(postBody);
                    console.log("添加一条记录后,data.json的内容:"  + JSON.stringify(list));
    
                    // 将json数组写入data.json文件
                    fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(list), function(err) {
                        if(err) throw err;
                        console.log('写入成功');
                    });
                });
                
                console.log("222...");
            });*/
    
            // 重定向
            res.statusCode = 302;
            res.statusMessage = 'Found';
            res.setHeader('Location', '/index');
            res.end(); 
        } 
        else if(req.url.startsWith('/detail') && req.method === 'get') {
            var queryId = urlObj.query.id;
    
            // 第一步:读取data.json文件中的数据,转换为list数组
            fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function (err, data) {
                if(err && err.code !== 'ENOENT') {throw err;}
                console.log("data.json原来的内容:" + data); // [{"name":"xxx","price":"xxx"}]]
                var bookList = JSON.parse(data || '[]'); // json数组
    
                // 查询指定id的记录
                var book = {};
                for (var i = 0; i < bookList.length; i++) {
                    if (bookList[i].id == queryId) { // 不能写“===”,因为queryId是字符串类型
                        book = bookList[i];
                    }
                }
    
                // 第二步:在服务器使用模版引擎,将数据和detail.html页面结合
                res.render(path.join(__dirname, 'pages/detail.html'), {book:book});
            });
        }
        else if(req.url.startsWith('/delete') && req.method === 'get') {
            var queryId = urlObj.query.id;
    
            // 第一步:读取data.json文件中的数据,转换为list数组
            fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function (err, data) {
                if(err && err.code !== 'ENOENT') {throw err;}
                console.log("data.json原来的内容:" + data); // [{"name":"xxx","price":"xxx"}]]
                var bookList = JSON.parse(data || '[]'); // json数组
                
                // 删除指定id的记录
                for (var i = 0; i < bookList.length; i++) {
                    if (bookList[i].id == queryId) {
                        bookList.splice(i, 1); // 删除起始下标为queryId-1,长度为1的元素
                    }
                }
    
                // 将json数组重新写入data.json文件
                fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(bookList), function(err) {
                    if(err) throw err;
                    console.log('写入成功');
                });    
    
    
                // 第二步:在服务器使用模版引擎,将bookList数据和list.html页面结合
                res.render(path.join(__dirname, 'pages/list.html'), {msg:'这是list页面', bookList:bookList});
            });
        }
        else if(req.url.includes('static')){
            res.render(path.join(__dirname, req.url));
        }
        else if(req.url.startsWith('/edit') && req.method === 'post') {
            var array = []; // 用来保存用户post请求提交的数据
            var postBody;
            req.on('data', function(chunk) {
                // chunk就是浏览器本次data事件提交的一部分数据;chunk是Buffer类型
                console.log("data事件...");
                array.push(chunk);
            });
    
            req.on('end', function() {
                console.log("end事件...");
                // 把array中多个Buffer对象汇总到一个Buffer对象
                postBody = Buffer.concat(array);
            });
    
            fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function (err, data) {
                if(err && err.code !== 'ENOENT') {throw err;}
    
                var bookList = JSON.parse(data || '[]'); // json数组
    
                // 获取get请求的参数,将用户提交的数据添加到json数组
                // querystring对象可以把表单数据 name=xxx&price=xxx => {"name":"xxx","price":"xxx"}
                var book = querystring.parse(postBody.toString("utf-8"));
                console.log("=============book:" + book.id + book.name + book.price);
                for (var i = 0; i < bookList.length; i++) {
                    // console.log("bookList[i].id=" + bookList[i].id);
                    // console.log("book.id=" + book.id);
                    // console.log(bookList[i].id == book.id);
                    if(bookList[i].id == book.id) {
                        bookList[i].name = book.name;
                        bookList[i].price = book.price;
                    }
                }
            
                // 将json数组重新写入data.json文件
                fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(bookList), function(err) {
                    if(err) throw err;
                    console.log('写入成功');
                });    
    
                // 重定向
                res.statusCode = 302;
                res.statusMessage = 'Found';
                res.setHeader('Location', '/list');
                res.end(); 
                });
        }
        else {
            res.writeHead(404, 'not found', {'Content-Type': 'text/html; charset=utf-8'});
            res.end("404,not found!");
        }
    }).listen('8080', function() {
        console.log('服务器已经启动,请访问http://127.0.0.1:8080/');
    });

    5、common.css

    h2 {
        background-color: #ccc;
    }

    6、html页面

      add.html

    <!DOCTYPE html>
    <html>
    <head>
        <title>add页面</title>
        <meta charset="utf-8">
        <link rel="stylesheet" type="text/css" href="/static/css/common.css">
    </head>
    <body>
        <h2>add页面</h2>
        <form method="get" action="/submit">
        <!-- <form method="post" action="/submit"> -->
            书名: <input type="text" name="name">
            价格: <input type="text" name="price">
            <input type="submit" value="添加">
        </form>
    </body>
    </html>

      detail.html

    <!DOCTYPE html>
    <html>
    <head>
        <title>detail页面</title>
        <meta charset="utf-8">
        <link rel="stylesheet" type="text/css" href="/static/css/common.css">
    </head>
    <body>
        <h2>detail页面</h2>
        <form method="post" action="/edit">
            <input type="hidden" name="id" value="<%= book.id %>">
            书名:<input type="text" name="name" value="<%= book.name %>"><br/>
            价格:<input type="text" name="price" value="<%= book.price %>"><br/>
            <input type="submit" value="修改">
        </form>
    </body>
    </html>

      index.html

    <!DOCTYPE html>
    <html>
    <head>
        <title>index页面</title>
        <meta charset="utf-8">
        <link rel="stylesheet" type="text/css" href="/static/css/common.css">
    </head>
    <body>
        <h2>index页面</h2>
        <!-- <img src="/static/images/1.jpg">
        <img src="/static/images/2.png"> -->
        <a href="/list">图书列表</a>
    </body>
    </html>

       list.html

    <!DOCTYPE html>
    <!DOCTYPE html>
    <html>
    <head>
        <title>list页面</title>
        <meta charset="utf-8">
        <link rel="stylesheet" type="text/css" href="/static/css/common.css">
    </head>
    <body>
        <h2>list页面</h2>
        <%= msg %>!</h2><br/>
        <!-- <img src="/static/images/1.jpg">
        <img src="/static/images/2.png"> -->
        <a href="/add">添加</a>
    
        <table border="1" cellpadding="0">
            <tr>
                <td>ID</td>
                <td>书名</td>
                <td>价格</td>
                <td>操作</td>
            </tr>
            <% for(var i = 0; i < bookList.length; i++) { %>
            <tr>
                <td><%= bookList[i].id %></td>
                <td><%= bookList[i].name %></td>
                <td><%= bookList[i].price %></td>
                <td>
                    <a href="/detail?id=<%= bookList[i].id %>">查看</a>
                    <a href="/delete?id=<%= bookList[i].id %>">删除</a>
                </td>
            </tr>
            <% } %>
        </table>
        
    </body>
    </html>

     7、node app.js启动项目,浏览器访问主页 :http://127.0.0.1:8080/

      

      

      

      测试完后data.json文件的数据:

    [{"id":1,"name":"射雕英雄传","price":"45.00"},{"id":2,"name":"天龙八部2","price":"66.00"},
    {"id":3,"name":"倚天屠龙记","price":"50.00"},{"id":4,"name":"Java编程思想2","price":"40.00"},
    {"name":"Java从入门到精通","price":"30.00","id":6},{"name":"ggf","price":"fff","id":8},
    {"name":"af","price":"ff","id":9}]

     

    8、封装app.js里面重复代码

    // 加载http模块
    var http = require("http");
    var fs = require("fs");
    var path = require("path");
    var mime = require("mime");
    var url = require("url");
    var querystring = require("querystring");
    var _ = require("underscore");
    
    // 创建一个http服务对象
    http.createServer(function(req, res) {
    
        req.url = req.url.toLowerCase();
        req.method = req.method.toLowerCase();
        if (req.method === 'get') { 
            // 通过url模块的parse方法获取用户get请求提交的数据
            // 第二个参数为true时,urlObj的query属性就是所有的请求参数,类型是json对象
            var urlObj = url.parse(req.url, true);
            // console.log(urlObj);
        }
    
        // 封装fender函数,将render函数挂在到res对象上;第二个参数是模板数据
        res.render = function (filename, templateData) {
            fs.readFile(filename, function(err, data) {
                if(err) {
                    res.writeHead(404, 'not found', {'Content-Type': 'text/html; charset=utf-8'});
                    res.end("404, not found.");
                    return;
                }
    
                if (templateData) {
                    var fn = _.template(data.toString("utf-8"));
                    data = fn(templateData);
                }
                
                res.setHeader('Content-Type', mime.getType(filename));
                res.end(data);
            });
        };
    
        if(req.url === '/' || req.url === '/index') {
            res.render(path.join(__dirname, 'pages/index.html'));
        } 
        else if(req.url === '/list') {
            // 第一步:读取data.json文件中的数据,转换为list数组
            readFile(function(bookList) {
                // 第二步:使用模版引擎,将bookList数据和list.html页面结合
                res.render(path.join(__dirname, 'pages/list.html'), {msg:'这是list页面', bookList:bookList});
            });
        } 
        else if(req.url.startsWith('/add')) {
            res.render(path.join(__dirname, 'pages/add.html'));
        } 
        else if(req.url.startsWith('/submit') && req.method === 'get') { // 如何获取get请求的参数
            // 用户表单提交get请求数据,保存到data/data.json文件中,新数据以追加的形式添加
            console.log(req.url); // /summit?name=xxx&price=xxx
    
            // 第一步:读取data.json文件中的数据,转换为list数组
            readFile(function(list) {
                // 第二步:获取get请求的参数,将用户提交的数据添加到json数组
                var book = urlObj.query;
                book.id = list[list.length - 1].id + 1;
                list.push(book);
                console.log("添加一条记录后,data.json的内容:"  + JSON.stringify(list));
                
                // 第三步:将json数组写入data.json文件,并重定向到list页面
                writeFile(list, res);
            });
        } 
        else if(req.url.startsWith('/submit') && req.method === 'post') { // 如何获取post请求的参数
            // 用户表单提交post请求数据,保存到data/data.json文件中,新数据以追加的形式添加
            getPostBodyData(req, function(book) { // post请求数据封装成book(json对象)
                // 读取data.json文件中的数据,转换为list数组
                readFile(function(list) {
                    book.id = list[list.length - 1].id + 1;
                    list.push(book);
                    // console.log("添加一条记录后,data.json的内容:"  + JSON.stringify(list));
                    
                    // 将json数组写入data.json文件,并重定向到list页面
                    writeFile(list, res);
                });
            });
        } 
        else if(req.url.startsWith('/detail') && req.method === 'get') {
            // 第一步:读取data.json文件中的数据,转换为list数组
            readFile(function(bookList) {
                // 第二步:查询指定id的记录
                var book = {};
                for (var i = 0; i < bookList.length; i++) {
                    // 不能写"===",因为urlObj.query.id是字符串类型
                    if (bookList[i].id == urlObj.query.id) {
                        book = bookList[i];
                        break;
                    }
                }
    
                // 第三步:使用模版引擎,将数据和detail.html页面结合
                res.render(path.join(__dirname, 'pages/detail.html'), {book:book});
            });
        }
        else if(req.url.startsWith('/delete') && req.method === 'get') {
            // 第一步:读取data.json文件中的数据,转换为list数组
            readFile(function(bookList) {
                // 第二步:删除指定id的记录
                for (var i = 0; i < bookList.length; i++) {
                    if (bookList[i].id == urlObj.query.id) {
                        bookList.splice(i, 1); // 删除起始下标为queryId-1,长度为1的元素
                        break;
                    }
                }
    
                // 第三步:将json数组重新写入data.json文件,并重定向到list页面
                writeFile(bookList, res);
            });
        }
        else if(req.url.includes('static')){
            res.render(path.join(__dirname, req.url));
        }
        else if(req.url.startsWith('/edit') && req.method === 'post') {
            getPostBodyData(req, function(book) { // post请求数据封装成book(json对象)
                console.log("=============book:" + book.id + book.name + book.price);
                // 读取data.json文件中的数据,转换为list数组
                readFile(function(bookList) {                
                    for (var i = 0; i < bookList.length; i++) {
                        // console.log("bookList[i].id=" + bookList[i].id);
                        // console.log("book.id=" + book.id);
                        console.log(bookList[i].id == book.id);
                        if(bookList[i].id == book.id) {
                            bookList[i].name = book.name;
                            bookList[i].price = book.price;
                            break;
                        }
                    }
                
                    // 将json数组重新写入data.json文件,并重定向到list页面
                    writeFile(bookList, res);
                });
            });
        }
        else {
            res.writeHead(404, 'not found', {'Content-Type': 'text/html; charset=utf-8'});
            res.end("404,not found!");
        }
    }).listen('8080', function() {
        console.log('服务器已经启动,请访问http://127.0.0.1:8080/');
    });
    
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 封装读取data.json文件的方法
    function readFile(callback) {
        fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function (err, data) {
            if(err && err.code !== 'ENOENT') {throw err;}
            console.log("data.json原来的内容:" + data); // [{"name":"xxx","price":"xxx"}]]
            var bookList = JSON.parse(data || '[]'); // json数组
            callback(bookList);
        });
    }
    
    // 封装写入data.json文件的方法
    function writeFile(list, res) { // 参数list的类型:json数组
        fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(list), function(err) {
            if(err) throw err;
            console.log('写入成功');
    
            // 重定向
            res.statusCode = 302;
            res.statusMessage = 'Found';
            res.setHeader('Location', '/list');
            res.end();
    
            // 使用模版引擎,将bookList数据和list.html页面结合
            // res.render(path.join(__dirname, 'pages/list.html'), {msg:'这是list页面', bookList:bookList});
        });    
    }
    
    // 封装写入data.json文件的方法
    function writeFile2(data, callback) { // 参数data的类型:字符串
        fs.writeFile(path.join(__dirname, 'data', 'data.json'), data, function(err) {
            if(err) throw err;
            console.log('写入成功');
    
            // 调用callback()来执行当写入数据完毕后的操作
            callback();
        });    
    }
    
    // 封装获取用户post提交的数据的方法
    function getPostBodyData(req, callback) {
        var array = []; // 用来保存用户post请求提交的数据
        var postBody;
        req.on('data', function(chunk) {
            // chunk就是浏览器本次data事件提交的一部分数据;chunk是Buffer类型
            console.log("data事件...");
            array.push(chunk);
        });
    
        req.on('end', function() {
            console.log("end事件...");
            // 把array中多个Buffer对象汇总到一个Buffer对象
            var postBody = Buffer.concat(array); // 此处postBody类型:Buffer
            // console.log("postBody: " + postBody); // postBody: name=1&price=1
            // querystring对象可以把表单数据 name=xxx&price=xxx => {"name":"xxx","price":"xxx"}
            postBody = querystring.parse(postBody.toString("utf-8")); // 此处postBody类型:json对象
            callback(postBody);
        });
    }
  • 相关阅读:
    EntityFramework优缺点
    领导者与管理者的区别
    七个对我最好的职业建议(精简版)
    The best career advice I’ve received
    Difference between Stored Procedure and Function in SQL Server
    2015年上半年一次通过 信息系统项目管理师
    Difference between WCF and Web API and WCF REST and Web Service
    What’s the difference between data mining and data warehousing?
    What is the difference between a Clustered and Non Clustered Index?
    用new创建函数的过程发生了什么
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/11141206.html
Copyright © 2011-2022 走看看