Node.js之Web学习笔记

Posted 二木成林

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Node.js之Web学习笔记相关的知识,希望对你有一定的参考价值。

http模块

入门

Node.js提供了系统模块http用来写服务端代码。http模块是系统核心模块,不需要下载只需要直接引入即可,引入代码如下:

var htttp = require('http');

创建简单的服务端代码如下:

// 第一步,引入http模块
var http = require("http");

// 第二步,通过http模块的createServer方法创建一个server
var server = http.createServer();

// 第三步,监听"request"事件,获取请求,发送响应
server.on("request", function (request, response) {
    console.log("接收到客服端请求,请求路径是:" + request.url);
});

// 第四步,设置监听端口,启动服务器
server.listen(8888, function () {
    console.log("服务器启动成功,可以通过 http://127.0.0.1:8888 来进行访问");
});

注意:

  • request是请求处理函数,会接收两个参数:Request请求对象和Response响应对象。请求对象Request可以获取客服端的一些请求信息,如请求路径;响应对象Response可以来给客服端发送响应消息。
  • listen()函数中的端口号可以任意设置。
  • 每次修改代码后要重启。

在浏览器输入http://localhost:8888/hello访问就可以在控制台看到打印结果:

响应数据给客户端

如果我们要响应一些数据给客服端,可以通过响应对象Response来输出一些信息。

  • response.write(data);:向客户端输出数据,可以多次调用该方法。
  • response.end();:结束输出。
// 第一步,引入http模块
var http = require("http");

// 第二步,通过http模块的createServer方法创建一个server
var server = http.createServer();

// 第三步,监听"request"事件,获取请求,发送响应
server.on("request", function (request, response) {
    console.log("接收到客服端请求,请求路径是:" + request.url);
    // 通过Response对象的write()方法可以向客户端输出数据
    response.write("hello world!\\n");
    response.write("hello node.js!");
    // 最后还要通过end()方法来结束输出,否则会一直等待
    response.end();
});

// 第四步,设置监听端口,启动服务器
server.listen(8888, function () {
    console.log("服务器启动成功,可以通过 http://127.0.0.1:8888 来进行访问");
});

在浏览器查看如下:

其实可以直接通过response.end(data);方法向客户端输出数据。

server.on("request", function (request, response) {
    console.log("接收到客服端请求,请求路径是:" + request.url);
    // 通过Response对象的end(data)方法可以向客户端输出数据
    response.end("hello world!")
});

根据不同请求路径返回不同数据

现在写的代码功能非常小,无论什么请求,响应的结果都是"hello world!",我们需要根据不同的请求路径来响应不同的结果,如/index响应首页、/login响应登录、/register响应注册等。可以通过if判断url来进行不同的响应:

// 第一步,引入http模块
var http = require("http");

// 第二步,通过http模块的createServer方法创建一个server
var server = http.createServer();

// 第三步,监听"request"事件,获取请求,发送响应
/*
根据不同的请求路径发送不同的响应结果:
1.获取请求路径
    通过request.url属性获取到请求的路径,即端口之后的那一部分路径,如"http://127.0.0.1:8888"默认是"/","http://127.0.0.1:8888/hello"是"/hello"
2.根据if判断来根据路径进行不同的响应返回
 */
server.on("request", function (request, response) {
    // 获取url属性,然后if判断
    var url = request.url;
    if (url === '/') {
        response.end('index page');
    } else if (url === '/hello') {
        response.end('hello world!');
    } else if (url === '/login') {
        response.end('login page');
    } else {
        response.end('404 Not Found.');
    }
});

// 第四步,设置监听端口,启动服务器
server.listen(8888, function () {
    console.log("服务器启动成功,可以通过 http://127.0.0.1:8888 来进行访问");
});

响应中文数据

当我们直接响应返回中文数据的时候,浏览器页面会中文乱码显示。因为node.js响应回的数据编码格式是UTF-8,而中文系统的浏览器页面解析用的是GBK。通过设置Content-Type响应头来设置响应数据内容的编码格式:

// 第一步,引入http模块
var http = require("http");

// 第二步,通过http模块的createServer方法创建一个server
var server = http.createServer();

// 第三步,监听"request"事件,获取请求,发送响应
server.on("request", function (request, response) {
    // 通过响应对象Response的setHeader(name, value)方法设置响应头,来设定响应数据内容是什么类型的
    response.setHeader('Content-Type', 'text/plain; charset=utf-8');
    response.end('hello 世界!');
});

// 第四步,设置监听端口,启动服务器
server.listen(8888, function () {
    console.log("服务器启动成功,可以通过 http://127.0.0.1:8888 来进行访问");
});

Content-Type还可以设置其他响应内容格式:

// 第一步,引入http模块
var http = require("http");
var fs = require("fs");

// 第二步,通过http模块的createServer方法创建一个server
var server = http.createServer();

// 第三步,监听"request"事件,获取请求,发送响应
server.on("request", function (request, response) {
    // 通过响应对象Response的setHeader(name, value)方法设置响应头,来设定响应数据内容是什么类型的
    var url = request.url;
    if (url === '/plain') {// 普通文本
        // text/plain是普通文本类型
        response.setHeader('Content-Type', 'text/plain; charset=utf-8');
        response.end('hello 世界!');
    } else if (url === '/html') {// 直接输出html内容
        // text/html是html格式的字符串
        response.setHeader('Content-Type', 'text/html; charset=utf-8');
        response.end("<p>hello node.js.<a href='#'>点我</a></p>")
    } else if (url === '/html-from-file') {// 从.html文件中读取内容
        fs.readFile('hello.html', function (err, data) {
            if (!err) {
                // text/html是html格式的字符串,通常读取.html文件中的内容
                response.setHeader('Content-Type', "text/html; charset=utf-8");
                response.end(data);
            } else {
                response.setHeader('Content-Type', 'text/plain; charset=utf-8');
                response.end('hello.html文件读取失败,请稍后重试!');
            }
        });
    } else if (url === '/star.jpg') {
        fs.readFile('star.jpg', function (err, data) {// 图片
            if (!err) {
                // data默认是二进制数据,可以通过data.toString()方法转换成能识别的字符串
                // response.end(chunk)方法中的参数支持两种数据类型:二进制和字符串
                // 图片就不需要指定编码了,通常只有字符串才需要指定编码
                response.setHeader('Content-Type', "image/jpeg");
                response.end(data);
            } else {
                response.setHeader('Content-Type', 'text/plain; charset=utf-8');
                response.end('hello.html文件读取失败,请稍后重试!');
            }
        });
    }
});

// 第四步,设置监听端口,启动服务器
server.listen(8888, function () {
    console.log("服务器启动成功,可以通过 http://127.0.0.1:8888 来进行访问");
});

代码风格

关于javascript代码规范,比较规范的有:

而关于JavaScript中分号是否添加的问题:

;`hello`.toString()
/*
当采用了无分号的代码风格时,只需要注意下面几个情况:
当一行代码是以(或[或`开头的时候,则在前面补一个分号就能避免一些语法解析错误。
所以会发现一些第三方代码中以;开头。
所以无论代码是否有分号,都建议如果一行代码是以(或[或`开头的,则最好都在前面补上
一个分号,有些人也会使用!或~符号,都是同样的效果。
*/

模板引擎art-template

概述

可以用来服务端渲染数据,然后直接传到客户端使用。

官方教程:art-template

推荐博客:模板引擎 – art-template

基本使用

我们可以通过响应对象Response的write或end方法向客户端输出文本数据,也可以输出html格式的字符串,更可以读取.html文件向客户端输出数据。如果我们向客户端输出大量数据,那么可能需要拼接html格式的字符串来显示不同的内容,例如:

// 导入http模块
var http = require("http");

// 创建服务器
var server = http.createServer();

// 监听request事件
server.on("request", function (request, response) {
    var name = "张三";
    var age = 18;
    var hobbies = ["听歌", "阅读", "打游戏"];
    // 拼接字符串
    var html = `
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Hello</title>
    </head>
    <body>
        <p>大家好,我的名字是:` + name + `</p>
        <p>我今年` + age + `岁了</p>
        <p>我的爱好有:` + hobbies[0] + `` + hobbies[1] + `` + hobbies[2] +
        `</p>
    </body>
    </html>
    `;
    response.end(html);
});

// 服务器监听端口,启动服务器
server.listen(8888, function () {
    console.log("服务器启动了!可以通过 http://127.0.0.1:8888 进行访问!")
});

但我们发现拼接字符串非常麻烦,如果html代码很多,那么就更麻烦了。所以可以使用模板引擎,在html文件中的一些关键信息用一些符号进行标记,然后统一进行替换。而art-template就是这样的一个模板引擎。使用的步骤如下:

// 第一步,安装art-template模块
npm install art-template
// 第二步,在js文件中引入该模块
var template = require('art-template');
// 第三步,使用参考API
template.render('模板字符串', 替换对象);

所以我们先在当前项目下安装art-template模块。

然后创建一个html文件,在里面使用模板引擎的{{ }}语法。其中{{ }}里面的变量名任意取,但遍历需要遵循模板引擎的语法格式。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
</head>
<body>
<p>大家好,我的名字是:{{ name }}</p>
<p>我今年{{ age }}岁了</p>
<p>我的爱好有:{{ each hobbies}} {{ $value }} {{ /each }}</p>
</body>
</html>

然后在js里通过读取.html文件的方式向客户端输出数据,并使用模板引擎渲染数据。

// 导入http模块
var http = require("http");
// 导入art-template模块
var template = require("art-template");
// 导入fs模块
var fs = require("fs");

// 创建服务器
var server = http.createServer();

// 监听request事件
server.on("request", function (request, response) {
    fs.readFile("./index.html", function (err, data) {
        if (!err) {
            // 默认读取到的data是二进制数据,模板引擎的render方法需要接收的是字符串,所以要将data转换成字符串才能给模板引擎使用
            var ret = template.render(data.toString(), {
                name: '张三',
                age: 19,
                hobbies: ['阅读', '听歌', '打游戏']
            });
            response.end(ret);
        }
    });
});

// 服务器监听端口,启动服务器
server.listen(8888, function () {
    console.log("服务器启动了!可以通过 http://127.0.0.1:8888 进行访问!")
});

注意:

  • template.render()方法在这里传入了两个参数,第一个参数就是写了模板语法的html字符串,不过这里传入的是从文件读取的html字符串;第二个参数是数据对象,里面定义了传给模板引擎的值,其中键名就是{{ }}里面的变量名,键值就是要赋予的具体值。
  • template.render()方法的返回值就是渲染数据成功返回的字符串,可以直接输出到客户端了。

在浏览器访问结果如下:

实例:文件浏览器

需求

需求:通过http模块和art-template模板引擎来实现文件浏览器的效果,如下图:

涉及知识

涉及模块:

  • http
  • fs
  • path

其他技术:

  • art-template模板引擎

实现原理:根据请求的路径使用fs模块直接读取系统中的文件目录及其相关属性,然后使用模板引擎art-template渲染出来。

代码实现(Windows系统)

在Windows系统下的代码和Linux系统下的路径有所区别:
app.js

var http = require('http');
var template = require('art-template');
var fs = require('fs');
var path = require('path');

var server = http.createServer();

server.on('request', function (request, response) {
    var url = request.url;
    if (url === '/') {
        fs.readFile('./index.html', function (err, data) {
            if (!err) {
                var files = [
                    {isDir: true, name: "C:/", path: "C:/"},
                    {isDir: true, name: "D:/", path: "D:/"},
                    {isDir: true, name: "E:/", path: "E:/"},
                    {isDir: true, name: "F:/", path: "F:/"},
                    {isDir: true, name: "G:/", path: "G:/"}];
                var ret = template.render(data.toString(), {files: files});
                response.end(ret);
            }
        });
    } else if (url.startsWith('/C:') || url.startsWith('/D:') || url.startsWith('/E:') || url.startsWith('/F:') || url.startsWith('/G:')) {
        url = decodeURIComponent(url.substring(1));// 中文是进行URL编码的,所以需要对路径进行解码
        // 根据目录路径读取该目录下的所有文件名称
        fs.readdir(url, function (err, files) {
            fs.readFile('./index.html', function (err, data) {
                if (!err) {
                    var paths = [];
                    for (var i in files) {
                        var item = new Object();
                        // 文件名
                        item.name = files[i];
                        // 文件绝对路径
                        var p = path.join(url, files[i]);
                        item.path = p;
                        if (files[i].startsWith('System Volume Information')) {
                            item.isDir = true;
                        } else if (files[i].startsWith(

以上是关于Node.js之Web学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

node.js学习笔记之简洁聊天室

将js进行到底:node学习笔记5

Node.js学习笔记

创业笔记-Node.js入门之一个完整的基于Node.js的web应用

node.js学习笔记之babel使用

node.js学习笔记之写文件