Node.js是一个基于Chrome V8引擎的JavaScript运行环境
官方地址:https://nodejs.org/zh-cn/
主要学习:JavaScript+Node.js
内置API模块(fs
、path
、http
等)+第三方API模块(express
、mysql
等)
环境安装:官网下载安装(推荐LTS版本)
查看版本:node-v
终端命令
执行代码:node app.js
fs模块是Node.js官方提供的、用来操作文件的模块,它提供了一系列的方法和属性,用来满足用户对文件的需求。
在JavaScript代码中,使用fs模块之前,需要先导入它:
const fs = require('fs')
fs.readFile('path','options',callback)
示例:
fs.readFile('./files/12.txt','utf8',function(err,dataStr){
//2.1打印失败的结果
//如果读取成功,则err的值为null
//如果读取失败,则err的值为错误对象,dataStr的值为underfined
console.log(err);
console.log('--------');
//2.2打印成功的结果
console.log(dataStr);
})
可以判断err
对象是否为null
,从而知晓文件读取的结果:
const fs = require('fs');
fs.readFile('./files/111.txt', 'utf-8', function (err, dataStr) {
if (err) {
return console.log('读取文件失败' + err.message); //读取文件失败ENOENT: no such file or directory, open 'E:\Web\Node.js\Day1\files\111.txt'
}
console.log('读取文件成功,结果是' + dataStr); //读取文件成功,结果是111
});
fs.writeFile('file','data','options',callback)
示例(判断是否写入成功):
//1.导入fs文件系统模块
const fs=require('fs')
fs.writeFile('./files/3.txt','ok123',function(err){
//如果文件写入成功,则err的值等于null
//如果文件写入失败,则err的值等于一个错误对象
// console.log(err);
if(err){
return console.log('文件写入失败!'+err.message);
}
console.log('文件写入成功');
})
原数据:
小红=99 小白=100 小黄=70 小黑=90
整理后:
小红:99
小白:100
小黄:70
小黑:90
代码:
const fs=require('fs')
//调用fs.readFile()读取文件内容
fs.readFile('./files/成绩.txt','utf-8',function(err,dataStr){
//判断是否读取成功
if(err){
return console.log('读取文件失败'+err.message);
}
// console.log('读取成功'+dataStr);
//4.1先把成绩的数据,按照空格进行分隔
const arrOld=dataStr.split(' ')
// console.log(arrOld);
// 4.2循环分割后的数组,对每一项数据,进行字符串的替换操作
const arrNew=[]
arrOld.forEach(item=>{
arrNew.push(item.replace('=',':'))
})
// 4.3把新数组中的每一项,进行合并,得到一个新的字符串
const newStr= arrNew.join('\r\n')
console.log(newStr);
//5.调用fs.writeFile()方法,把处理完的成绩,写入到新文件中
fs.writeFile('./files/成绩-ok.txt',newStr,function(err){
if(err){
return console.log('写入文件失败'+err.message);
}
console.log('成绩写入成功');
})
})
在使用fs模块操作文件时,直接提供完整的路径,不要提供./和../开头的相对路径,防止动态路径拼接出错。
// __dirname表示当前文件所处的目录
fs.readFile(__dirname+'/files/1.txt','utf-8',function(err,dataStr){
if(err){
return console.log('读取文件失败'+err.message);
}
console.log('读取文件成功'+dataStr);
})
path 模块是 Node.js 官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理 需求。
path.join()
方法:用来将多个路径拼接成一个完整的路径字符串。path.basename()
方法:用来从路径字符串中,将文件名解析出来。使用path模块之前,先导入:
const path = require('path')
path.join([...paths])
...paths<string>
路径片段的序列<string>
示例:
const pathStr = path.join('/a', '/b/c', '../', './d', 'e');
console.log(pathStr);//输出内容:\a\b\d\e
const pathStr1 = path.join(__dirname,'./files/1.txt');
console.log(pathStr1);//输出:当前文件所处目录/files/1.txt
注意:但凡涉及到路径拼接的操作,都要使用path.join()
方法进行处理,不要直接使用+
进行字符串拼接。
path.basename(path,ext)
此方法可以获取到路径中的最后一部分。
path
:必选参数,表示一个路径的字符串ext
:可选参数,表示文件扩展名示例:
//文件存放的路径
const fpath = 'a/b/c/index.html';
//文件名+扩展名
const fullName = path.basename(fpath);
console.log(fullName); //输出 index.html
//文件名
const nameWithoutExit = path.basename(fpath, '.html');
console.log(nameWithoutExit); //输出 index
path.extname(path)
示例:
//文件存放的路径
const fpath = 'a/b/c/index.html';
const kzm = path.extname(fpath);
console.log(kzm); //输出 html
在网络节点中,负责消费资源的电脑,叫做客户端;负责对外提供网络资源的电脑,叫做服务器。
http
模块是 Node.js
官方提供的、用来创建 web 服务器的模块。通过 http
模块提供的 http.createServer()
方法,就 能方便的把一台普通的电脑,变成一台 Web 服务器,从而对外提供 Web 资源服务。
1.导入htpp模块
const http = require('http')
2.创建web服务器实例
const server = http.createServer()
3.为服务器实例绑定request
事件
绑定request
事件,即可监听客户端发送过来的网络请求。
server.on('request',function(req,res){
console.log('Someone visit our web server');
})
4.启动服务器
调用服务器实例的.listen()方法,即可启动当前的web服务器实例.
server.listen(80,function(){
console.log('server running at http://127.0.0.1:80');
})
req请求对象
只要服务器接收到了客户端的请求,就会调用通过server.on()
为服务器绑定的request
事件处理函数。
如果想在事件处理函数中,访问与客户端相关的数据或属性,可以使用如下方式:
server.on('request',(req)=>{
//req是请求对象,它包含了与客户端相关的数据和属性
//req.url是客户端请求的URL地址
//req.method是客户端的method请求类型
const str = 'Your request url is $(req.url),and request method is ${req.method}'
console.log(str)
})
解决中午乱码问题
当调用 res.end()
方法,向客户端发送中文内容的时候,会出现乱码问题,此时,需要手动设置内容的编码格式:
server.on('request', (req,res)=> {
//定义一个字符串,包含中文内容
const str=`你请求的URL地址是 ${req.url},请求的method类似为 ${req.method}`
//调用res.setHeader()方法,设置响应头 Content-Type的值为text/html;charset=utf-8
res.setHeader('Content-Type','text/html;charset=utf-8')
res.end(str)
})
const http=require('http')
const server=http.createServer()
server.on('request',(req,res)=>{
//1.获取请求的url地址
const url=req.url
//2.设置默认的响应内容为404
let content='404 Not found'
//3.判断用户请求的是否为/或者/index.html页面 首页
if(url==='/'||url==='/index.html'){
content='<h1>首页</h1>'
//4.判断用户请求是否为/about.html页面
}else if(url==='/about.html'){
content='<h1>关于</h1>'
}
//5.设置响应头,防止中文乱码
res.setHeader('Content-Type','text/html;charset=utf-8')
//6.使用res.end()把内容响应给客户端
res.end(content)
})
server.listen(80,()=>{
console.log('server running at http://127.0.0.1');
})
Node.js中根据模块来源不同,将模块分为3个大类:
Node.js
官方提供的,例如fs
、path
、http
等.js
文件,都是自定义模块使用强大的require()
方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。
//1.加载内置的fs模块
const fs = require('fs')
//2,加载用户的自定义模块
const custom = require('./custom.js')
//3.加载第三方模块
const moment = require('moment')
注意:使用require()
方法加载其他模块时,会执行被加载模块中的代码。
和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。
//01模块
//在模块作用域中定义常量username
const username = '张三';
//在模块作用域中定义函数sayHello
function sayHello() {
console.log('大家好,我是' + username);
}
//02.js
const custom = require('./01');
//输出空对象,在02.js模块中,无法访问到01模块中的私有成员
console.log(custom);
好处:
防止了全局变量污染问题。
1.module
对象
在每个.js自定义模块中都有一个module
对象,它里面存储了和当前模块有关的信息:
2.module.exports
对象
在自定义模块中,可以使用 module.exports
对象,将模块内的成员共享出去,供外界使用。 外界用 require()
方法导入自定义模块时,得到的就是 module.exports
所指向的对象。
3.共享成员时的注意点
使用 require()
方法导入模块时,导入的结果,永远以 module.exports
指向的对象为准
4.exports
对象
由于 module.exports
单词写起来比较复杂,为了简化向外共享成员的代码,Node 提供了 exports
对象。
默认情况 下,exports
和 module.exports
指向同一个对象。
最终共享的结果,还是以 module.exports
指向的对象为准。
时刻谨记,require()
模块时,得到的永远是 module.exports
指向的对象:
注意:为了防止混乱,不要在同一个模块中同时使用exports
和module.exports
Node.js
遵循了 CommonJS
模块化规范,CommonJS
规定了模块的特性和各模块之间如何相互依赖。
CommonJS
规定:
module
变量代表当前模块。module
变量是一个对象,它的 exports
属性(即 module.exports
)是对外的接口。module.exports
属性。require()
方法用于加载模块。从 https://www.npmjs.com/ 网站上搜索自己所需要的包
从 https://registry.npmjs.org/ 服务器上下载自己需要的包
1.在项目中安装包的命令
npm intsall 包的完整名称
2.卸载包的命令
npm uninstall 包的完整名称
devDependencies
节点:包只在项目开发阶段会用到,在项目上线之后不会用到dependencies
节点:包在开发和项目上线之后都需要用到//安装指定的包,并记录到devDependencies节点中
npm i 包名 -D
npm install 包名 --save-dev
# 查看当前的下包镜像源
npm config get registry
# 将下包镜像源切换为淘宝镜像源
npm config set registry=https://registry.npm.taobao.org/
nrm
安装nrm小工具,利用nrm提供的终端命令,可以快速查看和切换下包的镜像源。
# 安装
npm i nrg -g
# 查看
nrm ls
# 切换
nrm use taobao
1.项目包
被安装到项目的 node_modules 目录中的包,都是项目包。
项目包又分两类:
npm i 包名 -D #开发依赖包
npm i 包名 -S #核心依赖包
2.全局包
在执行 npm install 命令时,如果提供了 -g
参数,则会把包安装为全局包。
全局包会被安装到 C:\Users\用户目录\AppData\Roaming\npm\node_modules
目录下。
npm i 包名 -g #全局安装指定的包
npm uninstall 包名 -g #卸载全局安装的包
注意:
模块在第一次加载后会被缓存。 这也意味着多次调用 require() 不会导致模块的代码被执行多次。
注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。
内置模块是由 Node.js
官方提供的模块,内置模块的加载优先级最高。
例如,require('fs')
始终返回内置的 fs
模块,即使在 node_modules
目录下有名字相同的包也叫做 fs
。
使用 require()
加载自定义模块时,必须指定以 ./ 或 ../
开头的路径标识符。
在加载自定义模块时,如果没有指定 ./
或 ../
这样的路径标识符,则 node
会把它当作内置模块或第三方模块进行加载。
同时,在使用 require()
导入自定义模块时,如果省略了文件的扩展名,则 Node.js 会按顺序分别尝试加载以下的文件:
如果传递给 require()
的模块标识符不是一个内置模块,也没有以 ‘./’ 或 ‘../’ 开头,则 Node.js
会从当前模块的父 目录开始,尝试从 /node_modules
文件夹中加载第三方模块。
如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录。
例如,假设在 'C:\Users\itheima\project\foo.js
' 文件里调用了 require('tools')
,则 Node.js
会按以下顺序查找:
当把目录作为模块标识符,传递给 require()
进行加载的时候,有三种加载方式:
package.json
的文件,并寻找 main
属性,作为 require()
加载的入口package.json
文件,或者 main
入口不存在或无法解析,则 Node.js
将会试图加载目录下的 index.js
文件。Node.js
会在终端打印错误消息,报告模块的缺失:Error: Cannot find module 'xxx‘