Node.js入门
概念
Node.js虽然带一个js后缀,但它实际是采用谷歌chrome浏览器V8引擎,由C++语言编写的一个js运行环境。
node.js不是一门语言,不是库、不是框架,就是一个Javascript运行时环境。Node.js可以解析执行Javascript代码。
以前只有浏览器可以解析执行Javascript代码,现在的Javascript可以完全脱离浏览器运行,一切都归功于Node.js
浏览器中的Javascript:
EcmaScript
BOM
DOM
Node.js中的Javascript:
没有BOM/DOM
EcmaScript
提供了一些服务器级别的操作API,这些API绝大多数都被包裹到一个具名的核心模块中,例如文件操作的 fs 核心模块、http服务构建的 http 模块,路径操作的 path 模块、操作系统的 os 模块等。
版本常识
偶数位为稳定版本 -0.6.x -8.x.x LTS(long time support长期支持版)
奇数位为非稳定版本 -0.7.x -9.x.x Current(体验版,最新特性版)
建议安装稳定版本
安装
windows下
直接在nodejs官网下载并点击下一步下一步进行安装即可。
完成后打开命令行工具直接输入 node -v,如果能够输出版本号就说明安装成功了
Mac下
升级系统到最新
升级xcode(下面的是通过命令行安装):
xcode-select -p(检查是否安装过,安装过会给返回一个路径地址,如果没有返回路径,接着执行下面的命令)
xcode-select --install
安装Homebrew(专门针对Mac的套件管理器)
打开brew官网https://brew.sh/,找到 Install Homebrew下面的命令复制到命令台回车。
brew install node回车
nodejs初体验
起一个web服务器
打开nodejs官网,点击 about 选项,将第一段代码复制到一个server.js中。
const http = require('http'); //加载http模块,用来创建web服务器及处理http相关的任务等等 const hostname = '127.0.0.1'; const port = 3000; const server = http.createServer((req, res) => { //通过createServer方法创建服务器 res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World\n'); }); server.listen(port, hostname, () => { //通过listen来监听服务器端口 console.log(`Server running at http://${hostname}:${port}/`); });
在sever.js文件处打开终端,在终端输入
node server.js
回车,即可看到终端输出
Server running at http://127.0.0.1:3000/
打开网址,可以看到是一个写着hello world的网页。
模块与包管理工具
Commonjs是一套规范。nodejs借鉴Commonjs并基于Commonjs的modules的管理规范实现了一套模块管理系统。在nodejs中,每一个文件都可以看做是一个单独的模块,在其中不需要有命名空间。不用担心变量污染。
在nodejs中,文件和模块是一一对应的。模块分为几种类型。大致可分为核心模块、用户自定义模块和通过npm安装的第三方模块。
根据模块的类型,有几种引入模块的方式:在nodejs中,可以通过文件路径来引入模块,也可以通过模块名称来引用。如果用文件名引用非核心模块,node会最终将文件名映射到对应的文件的路径。
使用模块的流程:创建模块 => 导出模块(exports.xx) => 加载模块(require(XX)) => 使用模块。
示例:在一个学校,有班级,有老师和学生。将学校看做一个模块,将班级看做一个模块(class.js),将老师看做一个模块(teacher.js),将学生看做一个模块(student.js)。
先从student.js开始,写入代码:
function add(student) { console.log('Add student: ' + student); } //将add方法暴露出去 exports.add = add;
teacher.js文件
function add(teacher) { console.log('Add teacher: ' + teacher); } //将add方法暴露出去 exports.add = add;
class.js代码
var student = require('./student'); var teacher = require('./teacher'); teacher.add('teacher1'); function add(teacherName, studentNames) { teacher.add(teacherName); studentNames.forEach(function (studentName) { student.add(studentName); }) } exports.add = add;
入口文件index.js
var classModule = require('./class'); classModule.add('teacher2', ['student1', 'student2']);
打开命令行,输入node index.js回车,就会输出我们添加的信息
主要 API总结
url(网址解析)
打开命令行,输入node进入node环境,输入url回车,会在命令行中打印出它的几个方法。
(1)parse
语法:url.parse(urlString[, parseQueryString[, slashesDenoteHost]])
urlString:要解析的url字符串
parseQueryString:布尔值,默认为false。如果设置为true,query属性将始终返回一个由querystring模块返回的一个对象。设置为false,则query属性将返回一个未解析的字符串。
slashesDenoteHost:布尔值,默认为false。如果设置为true,在//之后和/之前的字符串将被解析成域名host。
在命令行中输入
url.parse('http://www.cnblogs.com/lianglanlan/p/8665777.html')
回车后,命令行会输出
Url { protocol: 'http:', //底层使用的协议 slashes: true, //是否有双斜线 auth: null, host: 'www.cnblogs.com', //域名 port: null, //端口,默认为80 hostname: 'www.cnblogs.com', //主机名 hash: null, //锚点 search: null, //查询的字符串参数 query: null, //发送给服务器的数据 pathname: '/lianglanlan/p/8665777.html', //访问资源的路径名 path: '/lianglanlan/p/8665777.html', //路径 href: 'http://www.cnblogs.com/lianglanlan/p/8665777.html' }
可以看到url.parse已经把这个地址解析为一个对象。
对网址进行一下修改
url.parse('http://www.cnblogs.com:8080/lianglanlan/p/8665777.html?from=blog&author=lanlan#floor1')
回车后,命令行输出结果如下:
Url { protocol: 'http:', slashes: true, auth: null, host: 'www.cnblogs.com:8080', port: '8080', hostname: 'www.cnblogs.com', hash: '#floor1', search: '?from=blog&author=lanlan', query: 'from=blog&author=lanlan', pathname: '/lianglanlan/p/8665777.html', path: '/lianglanlan/p/8665777.html?from=blog&author=lanlan', href: 'http://www.cnblogs.com:8080/lianglanlan/p/8665777.html?from=blog&author=lanlan#floor1' }
将第二个参数设置为true,在命令行输入:
url.parse('http://www.cnblogs.com:8080/lianglanlan/p/8665777.html?from=blog&author=lanlan#floor1',true)
回车后命令行输出:
Url { protocol: 'http:', slashes: true, auth: null, host: 'www.cnblogs.com:8080', port: '8080', hostname: 'www.cnblogs.com', hash: '#floor1', search: '?from=blog&author=lanlan', query: { from: 'blog', author: 'lanlan' }, pathname: '/lianglanlan/p/8665777.html', path: '/lianglanlan/p/8665777.html?from=blog&author=lanlan', href: 'http://www.cnblogs.com:8080/lianglanlan/p/8665777.html?from=blog&author=lanlan#floor1' }
可以看到query的属性值变成了对象。
第三个参数,设置为false时
> url.parse('//www.cnblogs.com:8080/lianglanlan/p/8665777.html',true) Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: '', query: {}, pathname: '//www.cnblogs.com:8080/lianglanlan/p/8665777.html', path: '//www.cnblogs.com:8080/lianglanlan/p/8665777.html', href: '//www.cnblogs.com:8080/lianglanlan/p/8665777.html' }
可以看到,在url没有协议http或https时,host是不能正确解析出来的。
将第三个参数设为true:
> url.parse('//www.cnblogs.com:8080/lianglanlan/p/8665777.html',true,true) Url { protocol: null, slashes: true, auth: null, host: 'www.cnblogs.com:8080', port: '8080', hostname: 'www.cnblogs.com', hash: null, search: '', query: {}, pathname: '/lianglanlan/p/8665777.html', path: '/lianglanlan/p/8665777.html', href: '//www.cnblogs.com:8080/lianglanlan/p/8665777.html' }
可以看到host与path和pathname属性都能正确的解析出来。
(2)format
与parse作用相反,将上面用parse方法生成的对象传入给format
> url.format({protocol: 'http:', slashes: true, auth: null, host: 'www.cnblogs.c om:8080', port: '8080', hostname: 'www.cnblogs.com', hash: '#floor1', search: '? from=blog&author=lanlan', query: 'from=blog&author=lanlan', pathname: '/lianglan lan/p/8665777.html', path: '/lianglanlan/p/8665777.html?from=blog&author=lanlan' , href: 'http://www.cnblogs.com:8080/lianglanlan/p/8665777.html?from=blog&author =lanlan#floor1'})
回车后命令行输出
'http://www.cnblogs.com:8080/lianglanlan/p/8665777.html?from=blog&author=lanlan#floor1'
(3)resolve
进行url拼接处理
在命令行中输入
url.resolve('http://www.cnblogs.com/','/lanlan/p')
回车后,命令行输出
'http://www.cnblogs.com/lanlan/p'
QueryString
querystring模块用于解析或序列化请求参数的字符串。
(1)stringfy
序列化请求参数的字符串
语法:querystring.stringify(obj[, sep[, eq[, options]]])
obj:对象。要序列化的参数对象。
sep:字符串,默认为 & 。用于分隔查询字符串中的键值对的子字符串。
eq:字符串,默认为 = 。用于分隔查询字符串中键和值的子字符串。
options:对象,其中有encodeURIComponent方法。默认情况下需要编码为utf-8,如果需要替换编码,则需指定一个替代encideURIComponent选项。
示例:
//一个参数 > querystring.stringify({teacher:'teacher1',student:['student1','student2'],clas s:1}) 'teacher=teacher1&student=student1&student=student2&class=1' //三个参数 > querystring.stringify({teacher:'teacher1',student:['student1','student2'],clas s:1},';',':') 'teacher:teacher1;student:student1;student:student2;class:1'
(2)parse
将URL的querystring解析为键值对的组合(反序列化)。
语法:querystring.parse(str[, sep[, eq[, options]]])
参数与stringfy的相同。
>querystring.parse('teacher=teacher1&student=student1&student=student2&class=1') { teacher: 'teacher1', student: [ 'student1', 'student2' ], class: '1' } >
(3)escape(转义)与unescape(反转义)
> querystring.escape('<哈哈>') '%3C%E5%93%88%E5%93%88%3E' > querystring.unescape('%3C%E5%93%88%E5%93%88%3E') '<哈哈>'
http
HTTP具体概念参照:HTTP笔记
events