Node.js
是一个基于 Chrome V8 引擎的 JavaScript 运行环境。Js代码
的运行环境包括浏览器和Node.js。如果把Js代码
放在浏览器中运行那就说明我们在做前端开发,如果放在Node.js中执行那就说明我们在做后端开发。Node.js
中JavaScript 运行环境,V8引擎负责解析和执行js代码Node.js
作为一个 JavaScript 的运行环境,仅仅提供了基础的功能和 API。然而,基于 Node.js 提供的这些基础能,很多强大的工具和框架都出现了。1.fs 模块
是 Node.js
官方提供的、用来操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作需求。
fs.readFile() 方法,用来读取指定文件中的内容
fs.writeFile() 方法,用来向指定的文件中写入内容
2.如果要在 JavaScript 代码中,使用 fs 模块来操作文件,则需要使用如下的方式先导入它:
const fs = require('fs');
// 参数1:读取文件的存放路径
// 参数2:读取文件时候采用的编码格式,一般默认指定 utf8
// 参数3:回调函数,拿到读取失败和成功的结果 err data
const fs = require('fs');
// 1.txt是存在的文件 里面内容为:1111
fs.readFile('./1.txt', 'utf8', function(err, data) {
console.log(err);
console.log('------------------');
console.log(data);
})
打开中断PowerShell
或者cmd
,执行命令 node .\1.js
注意
:如果读取成功,则 err 的值为 null。data 的值为 1.txt中的内容
读取不存在的文件示例:
// 参数1:读取文件的存放路径
// 参数2:读取文件时候采用的编码格式,一般默认指定 utf8
// 参数3:回调函数,拿到读取失败和成功的结果 err data
const fs = require('fs');
// 11.txt是不存在的文件
fs.readFile('./11.txt', 'utf8', function(err, data) {
console.log(err);
console.log('------------------');
console.log(data);
})
打开中断PowerShell
或者cmd
,执行命令 node .\1.js
注意
:如果读取失败,则 err 的值为 错误对象,data 的值为 undefined
可以判断 err 对象是否为 null,从而知晓文件读取的结果:
const fs = require('fs');
fs.readFile('./11.txt', 'utf8', function(err, data) {
if (err) {
return console.log('读取文件失败!' + err.message);
}
console.log('读取文件成功!' + data);
})
示例
:如果文件2.txt
不存在,则会自动创建。如果本来就存在,则写入的内容会覆盖掉原来的内容。
const fs = require('fs');
fs.writeFile('./2.txt', 'abcd', function(err) {
console.log(err);
})
const fs = require('fs');
fs.writeFile('./3.txt', 'abcd', function(err) {
if (err) {
return console.log('文件写入失败!' + err.message);
}
console.log('文件写入成功!');
})
./
或 ../
开头的相对路径时,很容易出现路径动态拼接错误的问题。__dirname
表示当前文件所处的目录,不会随着执行 node 命令时所处的目录变化const fs = require('fs');
// __dirname 表示当前文件所处的目录
fs.readFile(__dirname + '/file/1.txt', 'utf8', function(err, data) {
if (err) {
return console.log('读取文件失败!' + err.message);
}
console.log('读取文件成功!' + data);
})
path 模块
是 Node.js
官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理需求。
path.join() 方法,用来将多个路径片段拼接成一个完整的路径字符串
path.basename() 方法,用来从路径字符串中,将文件名解析出来
如果要在 JavaScript 代码中,使用 path 模块来处理路径,则需要使用如下的方式先导入它:
const path = require('path');
使用 path.join() 方法,可以把多个路径片段拼接为完整的路径字符串,语法格式如下:
注意
:今后凡是涉及到路径拼接的操作,建议使用 path.join()
方法进行处理。不要直接使用 +
进行字符串的拼接
示例:
const path = require('path');
// ../会抵消掉/c
const pathStr = path.join('/a', '/b/c', '../', './d', 'e');
console.log(pathStr); // \a\b\d\e
// /file/1.txt 写成 ./file/1.txt也不会出错,但是如果用加号拼接会出错
const pathStr2 = path.join(__dirname, '/file/1.txt')
console.log(pathStr2);
使用 path.basename()
方法,可以获取路径中的最后一部分,经常通过这个方法获取路径中的文件名。
注意
:如果第二个参数存在,则只返回名字(不带扩展名)。
示例:
const path = require('path');
const fpath = '/a/b/c/index.html';
const fullname = path.basename(fpath);
console.log(fullname); // index.html
const name = path.basename(fpath, '.html');
console.log(name); //index
使用path.extname()
方法,可以获取路径中的扩展名部分
示例:
const path = require('path');
const fpath = '/a/b/c/index.html';
const fext = path.extname(fpath);
console.log(fext); // .html
IIS
、Apache
等。通过安装这些服务器软件,就能把一台普通的电脑变成一台 web 服务器。Node.js
中,我们不需要使用 IIS、Apache 等这些第三方 web 服务器软件。因为我们可以基于 Node.js 提供的http 模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外提供 web 服务。http.createServer()
方法,就能方便的把一台普通的电脑,变成一台 Web 服务器,从而对外提供 Web 资源服务。IP 地址的格式
:通常用“点分十进制”表示成(a.b.c.d)
的形式,其中,a,b,c,d 都是 0~255 之间的十进制整数。例如:用点分十进表示的 IP地址(192.168.1.1)在一台电脑中,可以运行成百上千个 web 服务。每个 web 服务都对应一个唯一的端口号。客户端发送过来的网络请求,通过端口号,可以被准确地交给对应的 web 服务进行处理。
在终端启动node .\http模块.js
,则会输出server running at http://127.0.0.1:8080
。
然后在浏览器中输入http://127.0.0.1:8080
,则会输出Someone visit our web server.
// 导入 http 模块
const http = require('http');
// 调用 http.createServer() 方法,即可快速创建一个 web 服务器实例
const server = http.createServer()
// 为服务器实例绑定 request 事件,即可监听客户端发送过来的网络请求
server.on('request', function(req, res) {
console.log('Someone visit our web server.');
})
// 调用服务器实例的 .listen() 方法,即可启动当前的 web 服务器实例
server.listen('8080', function() {
console.log('server running at http://127.0.0.1:8080');
})
注意
:8080为启动的端口,如果是80则http://127.0.0.1:80
后的:80
可以省略。
crt+c
可以停止服务器
req 请求对象
可以让服务器访问与客户端相关的数据或属性。比如req.url
是客户端请求的 URL 地址 ,req.method
是客户端请求的 method 类型。
// 导入 http 模块
const http = require('http');
// 调用 http.createServer() 方法,即可快速创建一个 web 服务器实例
const server = http.createServer()
// 为服务器实例绑定 request 事件,即可监听客户端发送过来的网络请求
server.on('request', function(req) {
// req.url 是客户端请求的 URL 地址 ,req.method 是客户端请求的 method 类型
const url = req.url
const method = req.method
const str = `Your request url is ${url}, and request method is ${method}`
console.log(str)
})
// 调用服务器实例的 .listen() 方法,即可启动当前的 web 服务器实例
server.listen('80', function() {
console.log('server running at http://127.0.0.1');
})
在终端启动node .\http模块.js
,则会输出server running at http://127.0.0.1
。
然后在浏览器中输入http://127.0.0.1
,则会输出Your request url is /, and request method is GET
在Postman中发起POST请求
在服务器的 request 事件处理函数中, 调用 res.end()
方法,可以向客户端响应一些内容
//
const http = require('http');
const server = http.createServer()
server.on('request', function(req, res) {
// req.url 是客户端请求的 URL 地址 ,req.method 是客户端请求的 method 类型
const url = req.url
const method = req.method
const str = `Your request url is ${url}, and request method is ${method}`
console.log(str)
// 调用 res.end() 方法,向客户端响应一些内容
res.end(str);
})
server.listen('80', function() {
console.log('server running at http://127.0.0.1');
})
当调用 res.end()
方法,向客户端发送中文内容的时候,会出现乱码问题
const http = require('http');
const server = http.createServer()
server.on('request', function(req, res) {
// req.url 是客户端请求的 URL 地址 ,req.method 是客户端请求的 method 类型
const str = `您请求的URL地址是 ${req.url}, 请求的method类型是 ${req.method}`
// 调用 res.end() 方法,向客户端响应一些内容
res.end(str);
})
server.listen('80', function() {
console.log('server running at http://127.0.0.1');
})
此时,需要调用 res.setHeader()
方法,设置 Content-Type 响应头:
const http = require('http');
const server = http.createServer()
server.on('request', function(req, res) {
// req.url 是客户端请求的 URL 地址 ,req.method 是客户端请求的 method 类型
const str = `您请求的URL地址是 ${req.url}, 请求的method类型是 ${req.method}`
// 调用 res.setHeader() 方法,设置 Content-Type 响应头,解决中文乱码的问题
res.setHeader('Content-Type', 'text/html;charset=utf-8')
// 调用 res.end() 方法,向客户端响应一些内容
res.end(str);
})
server.listen('80', function() {
console.log('server running at http://127.0.0.1');
})
获取请求的 url 地址,根据不同的url地址返回不同的内容
const http = require('http');
const server = http.createServer()
server.on('request', function(req, res) {
const url = req.url;
let content = '404 Not found!
'
if (url === '/' || url === '/index.html') {
content = '首页
'
} else if (url === '/about.html') {
content = '关于页面
'
}
res.setHeader('Content-Type', 'text/html; charset=utf-8')
res.end(content);
})
server.listen('80', function() {
console.log('server running at http://127.0.0.1');
})
1.Node.js
中根据模块来源的不同,将模块分为了 3 大类,分别是:
2.使用require()
方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。例如:
// 加载内置的fs模块
const fs = require('fs')
//加载用户自定义模块
const zdy = require('./自定义模块.js')
// 加载第三方模块
const moment = require('moment')
注意
:
console.log('加载了自定义模块!');
,则加载进来时,终端会打印这行信息。和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
如图,custom中为空。
在每个 .js
自定义模块中都有一个 module 对象,它里面 存储了和当前模块有关的信息,使用console.log(module)
打印如下:
我们可以使用 module.exports
对象,将模块内的成员共享出去,供外界使用。外界用 require()
方法导入自定义模块时,得到的就是 module.exports 所指向的对象。
注意:
在一个自定义模块中,默认情况下module.exports = {}
。
使用 require() 方法导入模块时,导入的结果永远以 module.exports 指向的对象为准。如图,module.export
指向了一个最新的对象,则require得到的模板的内容则是module.export
最新的对象。
由于 module.exports 单词写起来比较复杂,为了简化向外共享成员的代码,Node 提供了 exports 对象。默认情况下,exports 和 module.exports 指向同一个对象。
下面我们来分析 exports
和 module.exports
的使用误区。记住使用require() 模块时得到的永远是 module.exports 指向的对象:
Node.js
遵循了 CommonJS
模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖。
不同于 Node.js
中的内置模块与自定义模块,包是由第三方个人或团队开发出来的。
由于 Node.js
的内置模块仅提供了一些底层的 API,导致在基于内置模块进行项目开发的时,效率很低。包是基于内置模块封装出来的,提供了更高级、更方便的 API,极大的提高了开发效率。
我们可以在这个链接搜索自己需要的包,然后在电脑终端上执行npm install xx
或者npm i xx
下载 ( xx表示包,比如moment。)
注意
:在默认情况下,使用 npm install
命令安装包的时候,会自动安装最新版本的包。如果需要安装指定版本的包,可以在包名之后,通过 @ 符号指定具体的版本,例如:npm i [email protected]
初次装包完成后,在项目文件夹下多一个叫做 node_modules
的文件夹和 package-lock.json
、package.json
的配置文件。package.json
的配置文件,用来记录项目中安装了哪些包。从而方便剔除node_modules
(体积很大)目录之后,在团队成员之间共享项目的源代码。
包的版本号是以“点分十进制”形式进行定义的,总共有三位数字,例如 2.24.0
。其中每一位数字所代表的的含义如下:
注意
:版本号提升的规则:只要前面的版本号增长了,则后面的版本号归零。
package.json
文件中,有一个 dependencies
节点,专门用来记录您使用 npm install 命令安装了哪些包。
如果我们拿到的文件没有node_modules
,则可以通过 npm i
或者npm install
命令下载第三方包。执行该命令时,npm包管理工具
会先读取package.json中的dependencies节点,读取到记录的所有依赖包名称和版本号之后,会把这些包一次性下载到项目中。
可以运行 npm uninstall
命令,来卸载指定的包。npm uninstall
命令执行成功后,会把卸载的包,自动从 package.json 的 dependencies 中移除掉。
//两种写法相同 -D和包名的位置可以互换
npm i 包名 -D
npm install 包名 --save-dev
如果不知道放在 devDependencies
节点中还是 Dependencies
节点中,可以到https://www.npmjs.com/
中查看相关包的下载说明。比如webpack
的下载是需要放在 devDependencies
节点中的。
9. 在使用 npm 下包的时候,默认是从国外的 https://registry.npmjs.org/ 服务器进行下载的,下包速度会很慢。如果解决该问题,可查看该博客链接
使用 npm 包管理工具
下载的包,共分为两大类,分别是:项目包
、全局包
C:\Users\用户目录\AppData\Roaming\npm\node_modules
目录下。注意
:只有工具性质的包,才有全局安装的必要性。因为它们提供了好用的终端命令,比如nrm
。判断某个包是否需要全局安装后才能使用,可以参考官方提供的使用说明即可。i5ting_toc
是一个可以把md 文档
转为 html 页面
的小工具,使用步骤如下:
npm install -g i5ting_toc
,将其安装为全局包i5ting_toc -f day.md -o
,day.md
指要转化的md文档
, -o
参数表示要在转化成功后直接打开浏览器查看html页面模块在第一次加载后会被缓存。 这也意味着多次调用 require()
不会导致模块的代码被执行多次。
注意:
不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。
内置模块是由 Node.js
官方提供的模块,内置模块的加载优先级最高。例如,require('fs')
始终返回内置的fs 模块
,即使在 node_modules 目录下有名字相同的包也叫做fs
。
使用 require()
加载自定义模块时,必须指定以./
或 ../
开头的路径标识符。
在加载自定义模块时,如果没有指定 ./
或../
这样的路径标识符,则 node 会把它当作内置模块或第三方模块进行加载。
在使用 require()
导入自定义模块时,如果省略了文件的扩展名,则 Node.js 会按顺序分别尝试加载以下的文件:
require()
的模块标识符不是一个内置模块,也没有以 ‘./’ 或 ‘…/’ 开头,则 Node.js 会从当前模块的父目录开始,尝试从 /node_modules 文件夹中加载第三方模块。当把目录作为模块标识符,传递给 require()
进行加载的时候,有三种加载方式:
Express——基于 Node.js 平台的 web 应用开发框架链接