node.js个人笔记

Node.js

介绍

Node.js是什么?

  • Node.js不是一门语言。
  • Node.js不是库,不是框架。
  • Node.js是一个JavaScript运行时环境,即Node.js可以解析和执行JavaScript代码。

附:绝大多数JavaScript相关的包都存放在了npm上。

https://cnodejs.org/

https://nodejs.org/en/

Node.js中的JavaScript

  • 没有BOM,DOM。
  • EcmaScript。
  • 为JavaScript提供了一些服务器级别的API。
    • event-driven 事件驱动
    • non-blocking I/O model 非阻塞IO模型(异步)

Node.js能做什么?

  • web服务器后台。
  • 命令行工具
    • webpack
    • gulp
    • npm

安装nodejs

https://nodejs.org/zh-cn/

选择合适自己电脑的版本下载,傻瓜式安装包安装,安装过程略。

检测是否安装成功

打开cmd,输入 node –v 查看版本。

若出现以下现象代表安装成功,版本号可能有所不同。

扩展

安装了nodejs后,不单止可以用编译器运行js代码,也可以用命令行运行编译。

  1. 进入js的目录下
  2. 执行 node 文件名.js 命令

注意:不要以node.js命名。

起步

npm使用介绍

https://www.npmjs.com/

安装node默认就安装了npm。

npm --version 查看npm版本

  • 生成package.json文件:npm init

    • npm init -y 可以跳过向导,快速生成
  • 安装:npm install [--save] <Module Name> [- g]

    • 如果指定 -g 则是全局安装。
    • –save保存依赖包信息到package.json文件中。
  • 查看所有全局安装的模块:npm list -g

  • 查看某个模块:npm list <Module Name>

  • 卸载模块:npm uninstall [--save] <Module Name>

  • 更新模块:npm update <Module Name>

  • 搜索模块:npm search <Module Name>

  • 查看命令:npm help [<command>]

  • 清空NPM本地缓存:npm cache clear

解决npm被墙问题

npm存储包文件的服务器在国外,有时候会很慢,因而安装淘宝的cnpm(http://npm.taobao.org/):

npm insatll --global cnpm

接着就把npm的命令中npm替换成cnpm即可。

  • 如果不想安装cnpm又想使用淘宝的服务器来下载:
npm install 包名 --registry=https://registry.npm.taobao.org

但每一次手动加参数会很麻烦,但可以加上此配置:

npm config set registry https://registry.npm.taobao.org

# 查看 npm 配置信息
npm config list

ip地址和端口号(了解)

  • IP地址用来定位计算机
  • 端口号用来定位具体的应用程序,范围从0~65536之间。(所有需要联网通信的软件必须具有端口号)

模块版本号(x.y.z)

  • 如果只修复bug,则更新z位。
  • 增加功能,但向下兼容,更新y位。
  • 有大变动,但向下不兼容,更新x位。

核心模块

  • 文件操作:fs
  • http服务构建:http
  • 路径操作:path
  • 操作系统信息:os

Node 中的其他成员(fs文件操作注意)

在每个模块中,除了 requireexports 等模块相关API之外,还有两个特殊的成员:

  • __dirname 可以用来获取当前文件模块所属目录的绝对路径。
  • __filename 可以用来获取当前文件的绝对路径。
  • __dirname__filename是不受执行node命令所属目录影响的。

在文件操作中,使用相对路径是不可靠的,因为在Node中文件操作的路径被设计为相对于执行node命令所处的路径。
为了解决问题,只需把相对路径变为绝对路径,利用__dirname__filename

文件模块(自定义模块)(重要)

文件模块是用户自己编写的模块,**通过require加载,且通过相对路径加载时必须加./ **
在Node中没有全局作用域,只有模块作用域,即模块间不能相互访问到内部,也不能访问到外部。
每个文件模块中都提供了一个导出对象:exports
exports默认是一个空对象。
推荐加载时,.js 后缀省略。

模块系统(模块化)(重要)

模块规范
  • 模块作用域
  • 使用require方法加载模块
  • 使用exports接口对象用来导出模块中的成员。
加载模块require

通过 **require **指令用来载入使用Node.js模块。

作用:

  • 加载核心模块(或文件模块)并执行里面的代码。
  • 拿到被加载文件模块导出的接口对象exports
var fs = require('fs');
导出 exports
  1. 导出多个成员

    exports.a = 123;
    
  2. 导出一个成员

    module.exports = 'hello';
    

    以下情况会覆盖:

    module.exports = 'hello';
    // 后者覆盖前者
    module.exports = function (x, y) {
        return x + y;
    }
    

    也可以这样导出多个成员:

    module.exports = {
        add: function (x, y) {
            return x + y;
        },
        str: 'hello';
    }
    
原理解析

exports 和 module.exports 的一个引用。

console.log(exports === module.exports);

每一个模板都会隐藏着这一块代码。(必须理解,导出一个和多个为什么不同,引用类型赋值的问题)

var module = {
    exports: {}
}
exports = module.exports;
return module.exports;

例:

// a.js
console.log('a start');
require('./b.js');
console.log('a end');
/*
* 输出
* a start
* b start
* a end
* */

// b.js
console.log('b start');

因为模块间不能相互访问其内部,但可以通过 exports 导出。(核心模板原理也是这样)

// a.js
var b = require('./b');
console.log(b.foo);
console.log(b.add(10, 20));
/*
* 输出
* bbb
* 30
* */


// b.js
var foo = 'bbb';
exports.foo = foo;
exports.add = function(x, y) {
    return x + y;
}
require加载规则
  1. 优先从缓存加载

    // a.js
    require('./b.js');
    require('./c.js');
    // b.js
    console.log('b加载了');
    require('./c.js');
    // c.js
    console.log('c加载了');
    
    // 输出(注意a.js最后一个会优先从缓存加载,不会再把代码重复执行,只会加载模块了)
    // b加载了
    // c加载了
    
  2. 判断模块标识

    • 核心模块,官方的。

    • 第三方模块,加载语法与核心模块一样,但形式会不同,加载会首先搜索当前文件目录下的node_modules,然后搜索加载模块的名字,再找到模块目录下的package.json,找再到package.json中的main属性(记录了入口模块)。如果package.json或main属性不存在,默认加载模块目录下的index.js。

    • 自定义模块,一般采取相对路径加载。

注意:项目中有且只能有一个node_modeules。

package.json(重要)

建议每一个项目根目录都要有一个 **package.json **(就如产品的说明书)。

这个文件可以通过 npm init 的方式来自动初始化出来。

建议执行 npm install 包名 的时候都加上 --save 这个选项,目的是用来保存依赖项信息。

如果node_modules删除了,只需要 npm install 就会自动把package.json中的dependencies中所有的依赖项都下载回来。

package.json 和 package-lock.json

npm 5以前是不会有 package-lock.json 这个文件。以后版本才加入的。

当你安装包的时候,npm都会生成或者更新 package-lock.json 这个文件。

  • npm 5 以后的版本安装包不需要加 --save 参数,它会自动保存依懒信息。
  • 当安装包的时候,会自动创建或者是更新 package-lock.json 这个文件。
  • package-lock.json 这个文件会保存 node_modules 中所有包的信息(版本、下载地址)。
  • package-lock.json 这个文件另一个作用就是锁定版本号,防止自动升级。

回调地狱

一个回调函数放在另一个回调函数内,保证执行顺序。

在这里插入图片描述

解决它带来的问题,所以EcmaScript 6新增了一个API叫promise

promise(重要,ES6)

在这里插入图片描述

var fs = require('fs');
// 1.创建promise容器
var p1 = new Promise(function (resolve, reject) {
    fs.readFile('a.txt', 'utf8', function (err, data) {
        // 任务失败
        if (err) {
            // 把容器的pending状态改为Rejected
            // 相当于调用then第二个参数
            reject(err);
        } else {
            // 任务成功
            resolve(data);
        }
    })
});
var p2 = new Promise(function (resolve, reject) {
    fs.readFile('b.txt', 'utf8', function (err, data) {
        // 任务失败
        if (err) {
            // 把容器的pending状态改为Rejected
            // 相当于调用then第二个参数
            reject(err);
        } else {
            // 任务成功
            resolve(data);
        }
    })
});
var p3 = new Promise(function (resolve, reject) {
    fs.readFile('c.txt', 'utf8', function (err, data) {
        // 任务失败
        if (err) {
            // 把容器的pending状态改为Rejected
            // 相当于调用then第二个参数
            reject(err);
        } else {
            // 任务成功
            resolve(data);
        }
    })
});
// 当p1成功了,然后做指定的操作
// then方法第一个参数接收的function就是容器中的resolve函数
// 当return 一个promise对象的对象,后续的then中的方法的第一个参数会作为p2的resolve
p1.then(function (data) {
    console.log(data);
    return p2;
}, function (err) {
    console.log(err);
}).then(function (data) {
    console.log(data);
    return p3;
}).then(function (data) {
    console.log(data);
});
/**
 * 输出
 * aaaaaaaaaa
 * bbbbbbbbbbbb
 * cccccccccc
 */

以上代码冗余代码很多,因而一般会进行封装:

var fs = require('fs');

function pReadFile(filePath) {
    return new Promise(function (resolve, reject) {
        fs.readFile(filePath, 'utf8', function (err, data) {
            if (err) {
                reject(err);
            } else {
                resolve(data);
            }
        });
    });
}

pReadFile('a.txt').then(function (data) {
    console.log(data);
    return pReadFile('b.txt');
}).then(function (data) {
    console.log(data);
    return pReadFile('c.txt');
}).then(function (data) {
    console.log(data);
});

API

http://nodejs.cn/api/

文件系统(fs)

在Node中如果想要进行文件操作,就必须引入 fs 这个核心模块。
fs是file-system的简写,即文件系统,它提供了所有文件操作相关的API。

  • fs.readFile(path[, options], callbcak)
    • 读取文件内容。
    • path:文件名
    • options:字符编码
    • callback:回调函数
      • error:如果读取失败,error就是错误对象,成功则是null。
      • data:如果读取成功,data就是读取到的数据,失败则是null。
  • fs.writeFile(file, data[, options], callback)
    • 写入数据到文件
    • file:地址及文件名
    • data:数据
    • options:字符编码
    • callback:回调函数
      • error:如果写入失败,error就是错误对象,成功则是null。
  • fs.readdir(path[, options], callback)
    • 读取一个目录的内容。
    • path:目录地址。
    • options:字符编码。
    • callback:回调函数,含有err和data参数
var fs = require('fs');
// 写入数据
fs.writeFile('hello.txt', '大家好,你是猪', function (error) {
    if (error) {
        console.log('文件写入失败');
        return;
    }
    console.log('文件写入成功');
});

HTTP

  • http.createServer([options][, requestListener])

    • 创建web服务器,返回server对象。
  • server.listen(handle[, callback])

    • 绑定端口号,启动服务器。
    • handle:端口号
  • response.write(chunk,[, encoding][, callback])

    • 发送响应体数据块 。(不推荐)
    • chunk:字符串数据
    • encoding:字符编码
    • callback
  • response.end([data][, encoding][, callback])

    • 该方法会通知服务器,所有响应头和响应主体都已被发送,即服务器将其视为已完成。 (推荐)
    • data:字符串数据
    • encoding:字符编码
  • response.statusCode

    • 该属性控制响应头刷新时将被发送到客户端的状态码。
    • 301:永久重定向,浏览器会记住。
    • 302:临时重定向,浏览器不会记住。
  • respon.setHeader(name, vallue)

    • 为一个隐式的响应头设置值。

      res.setHeader('Content-Type', 'text/plain; charset=utf-8');
      
var http = require('http');
var fs = require('fs');
var server = http.createServer();
server.on('request', function (req, res) {
    var url = req.url;
    if (url === '/'){
        fs.readFile('../../Sy8/1.html', function (err, data) {
            if (err) {
                res.setHeader('Content-Type', 'text/plain; charset=utf-8');
                res.end('文件读取失败,请稍后重试!');
            } else {
                res.setHeader('Content-Type', 'text/html; charset=utf-8');
                res.end(data);
            }
        });
    }
});

server.listen(3000, function () {
    console.log('Server is running...');
});

URL

  • url.parse(urlString[, parseQueryString[, slashesDenoteHost]])
    • urlstring:要解析的 URL 字符串。
    • parseQueryString: 如果为 true,则 query 属性总会通过 querystring 模块的 parse() 方法生成一个对象。 如果为 false,则返回的 URL 对象上的 query 属性会是一个未解析、未解码的字符串。 默认为 false
    • slashesDenoteHost : 如果为 true,则 // 之后至下一个 / 之前的字符串会被解析作为 host。 默认false。

Path

  • path.basename(path[, ext])
    • 返回一个 path 的最后一部分 。
    • path:路径
    • ext:文件扩展名
  • path.dirname(path)
    • 返回 path 的目录名。
  • path.extname(path)
    • 返回 path 的扩展名。
  • path.isAbsolute(path)
    • 判断 path 是否为一个绝对路径。
  • path.parse(path)
    • 返回一个对象,对象的属性表示 path 的元素。
  • path.join([…paths])
    • 使用平台特定的分隔符把全部给定的 path 片段连接到一起,并规范化生成的路径。 长度为零的 path 片段会被忽略。 如果连接后的路径字符串是一个长度为零的字符串,则返回 '.',表示当前工作目录。
    • …paths:一个路径片段的序列

服务端渲染(使用模板引擎)

  • node.js也可以使用模板引擎。
  • 模板引擎不关心字符串的内容,只关心标记语法。

客户端渲染与服务端渲染区别

  • 客户端渲染(利用Ajax与模板引擎),在浏览器查看源代码看不到。
  • 服务端渲染是渲染好了再发给客户端,在源代码中看得到。
  • 客户端渲染不利于SEO搜索引擎优化。
  • 服务端渲染可被爬虫抓到,客户端异步渲染不行。

例:

var http = require('http');
var server = http.createServer();
var fs = require('fs');
// 引入模板引擎
var template = require('art-template');
var wwwDir = 'E:/Sourcecode/HTMLcode/Sy9';

server.on('request', function (req, res) {
    var url = req.url;
    fs.readFile('template-apache.html', function (err, data) {
        if (err) {
            return res.end('404 Not Found.');
        }
        fs.readdir(wwwDir, function (err, files) {
            if (err) {
                return res.end('Can not find www dir.');
            }
            // data默认为二进制数据,需要转换为字符串
            var htmlStr = template.render(data.toString(), {
                title: '哈哈',
                files: files
            });
            res.end(htmlStr);
        });
    });
});

server.listen(3000, function () {
    console.log('running');
});

template-apache.html

<html dir="ltr" lang="zh" i18n-processed="">
<head>
    <meta charset="utf-8">
    <meta name="google" value="notranslate">
    <style>
        h1 {
            border-bottom: 1px solid #c0c0c0;
            margin-bottom: 10px;
            padding-bottom: 10px;
            white-space: nowrap;
        }

        table {
            border-collapse: collapse;
        }

        th {
            cursor: pointer;
        }

        td.detailsColumn {
            -webkit-padding-start: 2em;
            text-align: end;
            white-space: nowrap;
        }

        a.icon {
            -webkit-padding-start: 1.5em;
            text-decoration: none;
        }

        a.icon:hover {
            text-decoration: underline;
        }

        a.file {
            background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC ") left top no-repeat;
        }

        a.dir {
            background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII= ") left top no-repeat;
        }

        a.up {
            background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC ") left top no-repeat;
        }

        html[dir=rtl] a {
            background-position-x: right;
        }

        #parentDirLinkBox {
            margin-bottom: 10px;
            padding-bottom: 10px;
        }

        #listingParsingErrorBox {
            border: 1px solid black;
            background: #fae691;
            padding: 10px;
            display: none;
        }
    </style>
    <title id="title">{{ title }}</title>
</head>

<body>
<div id="listingParsingErrorBox">糟糕!Google Chrome无法解读服务器所发送的数据。请<a
        href="http://code.google.com/p/chromium/issues/entry">报告错误</a>,并附上<a href="LOCATION">原始列表</a></div>
<h1 id="header">D:\Movie\www\ 的索引</h1>
<div id="parentDirLinkBox" style="display:none">
    <a id="parentDirLink" class="icon up">
        <span id="parentDirText">[上级目录]</span>
    </a>
</div>
<table>
    <thead>
    <tr class="header" id="theader">
        <th onclick="javascript:sortTable(0);">名称</th>
        <th class="detailsColumn" onclick="javascript:sortTable(1);">
            大小
        </th>
        <th class="detailsColumn" onclick="javascript:sortTable(2);">
            修改日期
        </th>
    </tr>
    </thead>
    <tbody id="tbody">
    {{each files}}
    <tr>
        <td data-value="apple/"><a class="icon dir" href="E:/Sourcecode/HTMLcode/Sy9">{{$value}}/</a></td>
        <td class="detailsColumn" data-value="0"></td>
        <td class="detailsColumn" data-value="1509589967">2017/11/2 上午10:32:47</td>
    </tr>
    {{/each}}
    </tbody>
</table>
</body>
</html>

使用Node操作MySQL数据库

https://www.npmjs.com/package/mysql

安装:

npm i mysql

使用:

var mysql = require('mysql');
// 创建连接
var connection = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: 'root',
    database: 'my_db'
});
// 连接数据库
connection.connect();
// 执行数据操作,增删改查都是用query
connection.query('SELECT 1 + 1 AS solution', function (error, results, fields) {
    if (error) throw error;
    console.log('The solution is: ', results[0].solution);
});
// 关闭连接
connection.end();

在Node中操作MongoDB(了解)

mongoDB 数据库的基本概念

  • 数据库
  • 集合(表)
  • 文档(表记录)
{
    qq:{ // 数据库
        users:[ // 集合
            {name: ''}, // 文档
            {name: ''},
            ...
        ]
    }
}

使用官方的 mongodb 包来操作

https://github.com/mongodb/node-mongodb-native

使用第三方mongoose来操作MongoDB 数据库

https://mongoosejs.com/

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
// 连接数据库
mongoose.connect('mongodb://localhost/test');
// 设计集合结构(表结构)
// 字段名称就是表结构中的属性名称
var blogSchma = new Schama({
    username: {
        type: String,
        required: true // 非空
    }
});
// 将文档结构发布为模型,返回模型构造函数
// 第一个参数是集合名称(大写名称单数字符串,会自动转为小写复数)
// 第二个参数是架构
var User = mongoose.model('User', blogSchma);
// 实例化一个 User
var kitty = new User({ name: 'Zildjian' });
// 持久化保持kitty实例
kitty.save(function (err, ret) {
    if (err) {
        console.log('err');
    } else {
        console.log(ret);
    }
});

Express(重要)

http://www.expressjs.com.cn/

起步

安装

npm install --save express

API

  • express.static(code)
    • 设置响应的HTTP状态。
  • req.query
    • 此属性是一个对象,包含路由中每个查询字符串参数的属性。如果没有查询字符串,则它是空对象{}。即返回get请求过来的数据对象。
  • res.redirect([status,] path)
    • 重定向到从指定的URL派生的URL path,具有指定的status与HTTP状态代码对应的正整数。如果未指定,则status默认为“302”Found“。

初使用

var express = require('express');
// 创建服务器,也就是http.createServer
var app = express();

// 公开指定目录,可以直接通过/public/xx访问public目录中的所有资源
app.use('/public/', express.static('./public/'));

// 当服务器收到get请求 / 的时候,执行回调函数
app.get('/', function (req, res) {
    // 响应数据
    res.send('hello express!');
});
app.get('/about', function (req, res) {
    res.send('你好,我是express!');
});
// 相当于 server.listen
app.listen(3000, function () {
    console.log('app is running at port 3000.');
});

基本路由

get:

app.get('/', function (req, res){
    res.send('Hello');
});

post:

app.post('/', function (req, res){
    res.send('world');
});

静态服务

// 当省略第一个参数的时候,则可以通过 省略 /public 的方式来访问,如127.0.0.1:3000/index.html<==>127.0.0.1:3000/public/index.html
app.use(express.static('/public/'));
// 当以 /public/ 开头的时候, 去 public 目录 目录找对应资源127.0.0.1:3000/static/index.html(推荐这种方式)
app.use('/public', express.static('public'));

app.use('/public', express.static(path.join(__dirname, 'public')));

在Express中配置使用 art-template 模板引擎

安装:

npm install --save art-template
npm install --save express-atr-template

配置

// 核心代码,配置使用art-template模板引擎,当渲染以 .art 结尾的文件的时候,使用atr-template模板引擎。
app.engine('art', require('express-art-template'));

// 如果想要修改默认的 views 视图渲染存储目录, 则可以
// app.set('views', render函数的默认路径);

使用

// res.render('html模板名', {模板数据});
// 第一个参数不能写路径,默认会去项目中的 views 目录查找该模板文件。
app.get('/', function (req, res) {
    res.render('index.art', {
        user: {
            name: 'aui',
            tags: ['art', 'template', 'nodejs']
        }
    });
});

在Express获取表单 POST 请求体数据

在Express中没有内置获取POST请求你体的API,需要使用第三方包:body-parser

安装:

npm install --save body-parser

配置:

var express = require('express');
// 引包
var bodyParser = require('body-parser');
var app = express();

// 配置body-parser
// 只要加入这个配置,则在req请求对象上会多出来一个属性:body
// 可以直接通过 req.body 来获取表单POST提交的数据
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());

使用:

app.use(function (req, res) {
  res.setHeader('Content-Type', 'text/plain');
  res.write('you posted:\n');
  res.end(JSON.stringify(req.body, null, 2));
})

**注意:**表单具有默认的提交行为,默认是同步的,同步表单提交,浏览器会锁死等待服务端的响应结果。表单的同步提交之后,无论服务端响应是什么,都会直接把响应的结果覆盖掉当前页面。

服务器重定向针对异步请求无效。

在Express配置使用express-session 插件

安装:

npm install express-session

配置:

app.use(session({
    // 配置加密字符串,它会在原有加密基础之上和这个字符串拼起来去加密
    // 目的是为了增加安全性
    secret: 'itcast',
    resave: false,
    // 无论是否使用session,都默认直接给你配一把钥匙
    saveUninitialized: true
}));

使用:

// 可以通过req.session来访问和设置Session成员
// 添加Session数据:
req.session.foo = 'bar';
// 访问Session数据:
req.session.foo

提示:默认Session数据是内存存储的,服务器一旦重启就会丢失,真正的生产环境会把Session持久化存储。

中间件

  1. 不关心请求路径和请求方法的中间件(即任何请求都会进入的中间件)

    app.use (function (req, res, next) {
        // 接收三个参数,req请求对象,response响应对象,next下一个中间件(也需要相匹配的)
       console.log('1');
        next();
    });
    

    当一个请求进入一个中间件之后,如果不调用next()则停留在当前中间件。

  2. 以 /xxx 开头的路径中间件

    app.use('/a', function (req, res, next) {
        console.log(req.url);
    });
    
  3. 严格匹配请求方法和请求路径的中间件

    app.get();
    app.post();
    
  4. 内置中间件

    • express.static
    • express.json
    • express.urlencoded
  5. 第三方中间件

    • body-parser
    • compression
    • cookie-parser
    • serve-static

路由器

路由器的行为类似于中间件本身,因此您可以将其用作 app.use() 的参数或作为另一个路由器的 use() 方法的参数。
顶级express对象具有一个用于创建新对象的Router()方法router
一旦你创建了一个路由器的对象,你可以添加中间件和HTTP方法路由(如getputpost,等),以它就像一个应用程序。例如:

一般用于模块化处理地址。

// a.js
var router = express.Router();
router.get('/', function(){
    // ...
});
router.post('/', function(){
    // ...
});
module.exports = router;

// b.js 程序入口
var app = express();
var fun = require('./a.js');
// 把路由容器挂载到 app服务中
app.use(fun);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值