node.js 示例

1. form.js

var fs = require('fs'); // require加載都是同步的
var mime = require('mime');
var path = require('path');
var http = require('http');
var url = require('url');
var querystrng = require('querystring');
var _ = require('underscore');

http.createServer(function(req, res) {

    req.url = req.url.toLowerCase();
    req.method = req.method.toLowerCase();
    var urlObj = url.parse(req.url, true); // 傳入true解析,獲取用戶提交的數據

    // 封裝一個render函數
    res.render = function(filename, tplData) {
        fs.readFile(filename, function(err, data) {
            if(err) {
                res.writeHead(404, 'Not Found', {'Content-Type': 'text/html;charset=utf-8'});
                res.end();
                return;
            }

            // 如果用戶傳遞了模板數據,表示要進行模板替換,加載underscore
            if(tplData) {
                var fn = _.template(data.toString('utf-8'));
                data = fn(tplData);
            }
            res.setHeader('Content-Type', mime.getType(filename));
            res.end(data);
        });
    }

    if(req.url === '/' || req.url === '/form' && req.method === 'get') {
        readNewsData(function(list) {
            res.render(path.join(__dirname, 'htmls', 'form.html'), {list: list});
        })
    } else if(req.url.startsWith('/add') && req.method === 'get') {

        readNewsData(function(list) {
            urlObj.query.id = list.length; // 添加id
            list.push(urlObj.query); // 新數據寫入list數組

            // 所有數據全部重新寫入data.json文件
            writeNewsData(JSON.stringify(list), function() {
                res.statusCode = 302; // 以3開頭的狀態碼錶示跳轉
                res.statusMessage = 'Found';
                res.setHeader('Location','/'); // 瀏覽器重定向,跳轉到localhost:9090
                res.end();
            })
        })
    } else if(req.url.startsWith('/add') && req.method === 'post') {

        readNewsData(function(list) {
            postBodyData(req, function(postBody) {
            
                postBody.id = list.length; // 添加id

                list.push(postBody);

                // 未封裝的寫入data.json文件的代碼
                fs.writeFile(path.join(__dirname, 'data', 'data.json'), JSON.stringify(list), function(err) {
                    if(err) {
                        throw err;
                    }
                    console.log('ok');
                    res.statusCode = 302; // 以3開頭的狀態碼錶示跳轉
                    res.statusMessage = 'Found';
                    res.setHeader('Location','/'); // 瀏覽器重定向,跳轉到localhost:9090
                    res.end();
                })
            })
        })
    } else if(urlObj.pathname === '/item' && req.method === 'get') {

        // 未封裝的讀取data.json文件的代碼
        fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function(err, data) { // utf-8返回字符串
            if(err && err.code !== 'ENOENT') { // 報錯且文件存在
                throw err;
            }
            var list = JSON.parse(data || '[]');
            
            var model = null;
            for(var i=0; i<list.length; i++) { // 循環,找到id相等的數據
                if(list[i].id.toString() === urlObj.query.id ) {
                    model = list[i];
                    break;
                }
            }

            if(model) {
                res.render(path.join(__dirname, 'htmls', 'details.html'), {item: model});
            } else {
                res.end('No such item');
            }
        })
    } else {
        res.setHeader('Content-Type', 'text/plain; charset=utf-8');
        res.end('404, not Found,客戶端錯誤!')
    }
}).listen(9090, function() {
    console.log('http://localhost:9090');
});

// 封裝一個讀取data.json文件的函數,函數異步執行只能通過回調函數返回
function readNewsData(callback) {
    fs.readFile(path.join(__dirname, 'data', 'data.json'), 'utf-8', function(err, data) { // utf-8返回字符串
        if(err && err.code !== 'ENOENT') { // 報錯且文件存在
            throw err;
        }
        var list = JSON.parse(data || '[]'); // 原有數據轉換成數組,防止get提交的數據被覆蓋
        callback(list); // 通過調用回調含糊callback將讀取到的數據list傳遞出去
    })
}

// 封裝的寫入data.json文件的代碼
function writeNewsData(list, callback) {
    fs.writeFile(path.join(__dirname, 'data', 'data.json'), list, function(err) {
        if(err) {
            throw err;
        }
        callback();
    })
}

// 封裝獲取用戶post提交的數據
function postBodyData(req, callback) {
    // post方法提交數據可能數據量較大,分多次提交,所以必須監聽request的data事件,request的end事件標誌提交結束
    var arr = [];
    req.on('data', function(chunk) {
        arr.push(chunk); // chunk的數據類型是Buffer,瀏覽器提交過來的一部分數據
    });
    req.on('end', function() {

        var postBody = Buffer.concat(arr); // 轉換成一個大的Buffer對象
        postBody = postBody.toString('utf-8'); // Buffer對象轉換成一個字符串,name=Karry&age=21
        postBody = querystrng.parse(postBody); // 轉換成json對象,{name: 'Karry', age: 21}

        callback(postBody); // 把post提交的數據傳遞出去
    })
}

2. form.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
    form {
        margin: 40px auto;
        width: 200px;
    }
    input[type="text"] {
        width: 100px;
    }
    input[type="submit"] {
        width: 60px;
    }
    table {
        background-color: rgba(250, 235, 215, 0.726);
        width: 100px;
        margin: 100px auto;
    }
</style>
</head>
<body>
<form action="/add" method="get" name="info">
    姓名:<input type="text" name="name" id="name"><br><br>
    年齡:<input type="text" name="age" id="age"><br><br>
    <input type="submit" value="submit">
</form>
<form action="/add" method="post" name="info">
    姓名:<input type="text" name="name" id="name"><br><br>
    年齡:<input type="text" name="age" id="age"><br><br>
    <input type="submit" value="submit">
</form>
<table border="1px" cellpadding="0" cellspacing="0">
    <% for(var i=0; i<list.length; i++) { %>
        <tr>
            <td>
                <a href="/item?id=<%= list[i].id %>">
                    <%= list[i].name %>
                </a>
            </td> 
            <td>
                <a href="/item?id=<%= list[i].id %>">
                    <%= list[i].age %>
                </a>
            </td>     
        </tr>
    <% } %>
</table>
</body>
</html>

3. details.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
    <h3><%= item.name %></h3>
    <p>2020年,<%= item.age %>歲了</p>
</body>
</html>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章