node.js知识整理
node.js
认识node.js
node.js是独立执行javaScript代码的环境
node.js和浏览器环境的Js最大区别:
node.js环境中没有BOM和DOM
如何用:
注意,下载安装后不要再变路径了,不然会出问题。
在vscode里面对应的JS文件右击–在集成终端中打开–输入node xx.js,xx 是文件名,然后就可以执行js文件
作用:编写后端程序:提供数据和网页资源等
前端工程化:集成各种开发中使用的工具和技术
url中的端口号:
端口号
http: //hmajax.itheima.net:80/api/province
其中:80就是端口号
标记服务器里不同功能的服务程序端口号
范围:0-65535之间的任意整数
http协议,默认访问80端口
在Node.js中执行js代码(注意路径):
打开终端,输入node要执行的js文件(以.js结尾)路径
先切换到执行文件所处的路径:终端输入 cd js所在的文件夹路径(或者直接在这个文件夹里面右键打开终端)
然后再输入node xx.js
注意!!要切换到文件所在的文件夹运行文件,尽量不要拼接路径,不要用./或../的相对路径,容易动态拼接失败
也可以提供完整的路径,但是移植性差,不利于维护,如:
fs.readFile(‘C:\Users\escook\Desktop\Node.js基础\day1\code\files\1.txt’, ‘utf8’, function(err, dataStr) {
if (err) {
return console.log(‘读取文件失败!’ + err.message)
}
console.log(‘读取文件成功!’ + dataStr)
})
推荐:使用__dirname表示当前文件所处的路径
console.log(__dirname)打印的是当前文件所处的路径
如:
fs.readFile(__dirname + ‘/files/1.txt’, ‘utf8’, function(err, dataStr) {
if (err) {
return console.log(‘读取文件失败!’ + err.message)
}
console.log(‘读取文件成功!’ + dataStr)
})
node中的全局对象
- node中的常见对象
全局对象–global===globalThis
(类似window)
module,exports,require(),Buffer
- 特殊的对象
这个对线实际上是模块中的变量,每个模块都有,看起来像全局变量
_dirname 打印显示当前文件的目录结构(常用)
_filename 打印显示当前文件的目录结构+文件名称
- 模块化时重要的对象
module,exports,require(后面详细讲解) - 定时器函数
setTimeout()
,setInterval()
setImmdiate()
立即执行,事件循环中用,process.nextTick()
额外执行函数,事件循环中用
(后面两个谁先执行不一定)(面试可能会问)
JS模块化开发
什么是模块化开发
(图片转文字)
CommonJS规范(CJS)和Node关系
CommonJS是一个大家都认同的规范,每个框架里都有自己的实现。最早规范在服务器里,后面也用于浏览器
主要包含两个规范:
模块中导出内容用exports
模块中导入内容用require
A模块定义的数据和规则,B想要用,那么A要把东西导出,B导入
A中 exports exKey1=Key1
B中 require re=("./a文件名.js")
- 这里的re相当于直接获取导出的对象,下面代码通过re.属性名或re.函数名进行使用,但是有更简单的方法:
- **在开发中,最常用的是导入一个文件后对需要用到的对象进行结构,把属性结构出来,用起来更方便 **
exports和require的本质–引用赋值
exports默认是一个空对象exports={}
,在进行导出时相当于给对象添加属性
require原理:当通过const bar = require()
函数拿到对象,相当于返回的是这个对象的引用地址,本质是引用赋值
(图片)
module.exports导出(用的多)
单独exports导出效果等同于用module.exports.Key1=Key1
导出;导入代码不用改变
在内存中有一个module对象,里面有exports属性;这两种方法指向的都是同一个对象,如果修改改的是同样的东西
(图片)
Node导出的本质(内存)+最常用写法
本质是在导出module中的export
开发中最常用的写法是:
1 | module.exports = { |
写大括号就会创建新对象开辟新的内存
这样再export.key1=新赋值修改key1没有意义,修改原来的对象不会影响到我拿到的新对象;但是module.exports.Key1=新赋值才会修改我拿到的对象
模块
fs文件系统模块
是Node.js官方提供的用来操作文件的模块
在js代码中要使用fs模块,需要先导入:const fs = require(‘fs’)
读取文件
fs.readFile()方法:用来读取指定文件中的内容
语法:fs.readFile(path[,option],callback)
path:文件路径,如./file/hello.txt
option:可选路径,表示以什么编码格式读取文件
callback:读取完成后通过回调函数拿到读取的结果,如function(err,dataStr){
console.log(err) //如果读取成功err为null,失败为错误对象
console.log(dataStr) //如果失败这里是undefined
}
如:const fs = require(‘fs’)
fs.readFile(‘./files/hello.txt’, ‘utf8’, function(err, dataStr) {
if (err) {
return console.log(‘读取文件失败!’ + err.message)
}
console.log(‘读取文件成功!’ + dataStr)
})
写入文件
fs.writeFile()方法:用来向指定问价中写入内容
语法:fs.writeFile(path,data[,option],callback)
path:文件路径,如./file/hello.txt
data:要写入的内容
option:可选路径,表示以什么编码格式写入文件,默认utf8
callback:写入完成后的回调函数
如:const fs = require(‘fs’)
fs.writeFile(‘./files/3.txt’, ‘晚上好呀’, function(err) {//如果写入成功,err=null 如果写入失败,err的值是一个错误对象
if (err) {
return console.log(‘文件写入失败!’ + err.message)
}
console.log(‘文件写入成功!’)
})
练习
const fs = require(‘fs’)
// 2. 调用 fs.readFile() 读取文件的内容
fs.readFile(‘../素材/成绩.txt’, ‘utf8’, function(err, dataStr) {
// 3. 判断是否读取成功
if (err) {
return console.log(‘读取文件失败!’ + err.message)
}
// console.log(‘读取文件成功!’ + dataStr)
// 4.1 先把成绩的数据,按照空格进行分割
const arrOld = dataStr.split(‘ ‘)
// 4.2 循环分割后的数组,对每一项数据,进行字符串的替换操作
const arrNew = []
arrOld.forEach(item => {
arrNew.push(item.replace(‘=’, ‘:’))
})
// 4.3 把新数组中的每一项,进行合并,得到一个新的字符串
const newStr = arrNew.join(‘\r\n’)
// 5. 调用 fs.writeFile() 方法,把处理完毕的成绩,写入到新文件中
fs.writeFile(‘./files/成绩-ok.txt’, newStr, function(err) {
if (err) {
return console.log(‘写入文件失败!’ + err.message)
}
console.log(‘成绩写入成功!’)
})
})
path路径模块
是官方提供的用来处理路径的模块,提供了一系列的方法和属性满足用户对路径的处理需求
养成路径不写中文的好习惯!!!!!!!!!!
在js代码中要使用fs模块,需要先导入:const path = require(‘path’)
路径拼接
path.join():将多个路径片段拼接成一个完整的路径字符串
语法:path.join([…paths])
…pathsz
返回值:
../ 会抵消前面的路径
如:
const path = require(‘path’)
const fs = require(‘fs’)
// 注意: ../ 会抵消前面的路径,前面的c被抵消了
const pathStr = path.join(‘/a’, ‘/b/c’, ‘../../‘, ‘./d’, ‘e’)
console.log(pathStr) // \a\b\d\e
fs.readFile(__dirname + ‘/files/1.txt’)
__dirname到达当前文件夹,拼接当前文件目录:
fs.readFile(path.join(__dirname, ‘./files/1.txt’), ‘utf8’, function(err, dataStr) {
if (err) {
return console.log(err.message)
}
console.log(dataStr)
})
通过路径获取文件名
path.basename():从路径字符串中,获取路径中的最后一部分,通常用于将文件名解析出来
语法:path.basename(path[,ext])
path:一个路径的字符串
ext
返回
如:
const path = require(‘path’)
// 定义文件的存放路径
const fpath = ‘/a/b/c/index.html’
const fullName = path.basename(fpath)
console.log(fullName) //输出index.html
const nameWithoutExt = path.basename(fpath, ‘.html’)
console.log(nameWithoutExt) //输出index
http模块
是用来创建web服务器的模块,通过http模块提供的http.createServe()方法可以把一台普通的电脑变成一台web服务器
要使用http模块,要先导入const http = require(‘http’)
创建最基本的web服务器
- 导入 http 模块
const http = require(‘http’) - 创建 web 服务器实例
const server = http.createServer() - 为服务器实例绑定 request 事件,监听客户端的请求
只要有客户端来请求自己的服务器,就会触发request事件,从而调用这个事件处理函数
server.on(‘request’, function (req, res)=>{
console.log(‘Someone visit our web server.’)
}) - 启动服务器
调用服务器实例的,listen(端口号,cb回调)方法,启动web服务器
server.listen(8080, function () {
console.log(‘server running at http://127.0.0.1:8080‘)
})
req请求对象
req请求对象:只要服务器接收到了客户端的请求,就会调用通过serve.on()为服务器绑定的request事件处理函数
req包含了与客户端相关的数据和属性如url,mrthod
如:
const http = require(‘http’)
const server = http.createServer()
server.on(‘request’, (req, res) => {
// req.url 是客户端请求的 URL 地址
const url = req.url
// req.method 是客户端请求的 method 类型
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, () => {
console.log(‘server running at http://127.0.0.1‘)
})
解决中文乱码
res.setHeader() 方法,设置 Content-Type 响应头,解决中文乱码的问题
res.setHeader(‘Content-Type’, ‘text/html; charset=utf-8’)
如:
const http = require(‘http’)
const server = http.createServer()
server.on(‘request’, (req, res) => {
// 定义一个字符串,包含中文的内容
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, () => {
console.log(‘server running at http://127.0.0.1‘)
})
根据不同的url响应不同的html内容
const http = require(‘http’)
const server = http.createServer()
server.on(‘request’, (req, res) => {
// 1. 获取请求的 url 地址
const url = req.url
// 2. 设置默认的响应内容为 404 Not found
let content = ‘
404 Not found!
‘// 3. 判断用户请求的是否为 / 或 /index.html 首页
// 4. 判断用户请求的是否为 /about.html 关于页面
if (url === ‘/‘ || url === ‘/index.html’) {
content = ‘
首页
‘} else if (url === ‘/about.html’) {
content = ‘
关于页面
‘}
// 5. 设置 Content-Type 响应头,防止中文乱码
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‘)
})
模块化
理解:提高代码复用性,就像学后端的时候把常用的功能封装成一个个函数,放到tool.java中,就是模块化开发,别的地方要用直接调用这个函数就可以,这里也是,别的地方要用这个功能直接调用这个模块就可以,就是在B.js中要调用A.js中的功能。
每一个模块都是单独的,都有自己独立的作用域
要使用标准语法,来把模块内想要使用的方法或属性进行导出和导入
CommonJS标准-导入导出
node.js默认支持这个标准语法
导出:
module.exports={
对外属性名1:属性值.
对外属性名2:属性值.
对外方法1:方法
}
导入:require(‘模块名或路径’)
如果导入内置模块(fs,path,http)写模块名
如果导入自己写的模块,要写路径如const obj=require(./A.js)
后面可以const result = obj.导出的属性名或方法名来接收使用
ECMAScript 标准-默认导出和导入
要使用这个标准,需要在运行模块所在的文件夹新建package.json文件,并设置{“type”:”module”}就是把这行代码写进去
导出:
export default{
对外属性名1:属性值.
对外属性名2:属性值.
对外方法1:方法
}
导入:import 变量名 from’模块名或路径’
这个变量名就相当于export deafult导出的对象
ECMAScript 标准-命名导出和导入
导出:export修饰定义语句
如:
export const baseURL =’http://xxxx.xxx.net
export const getArraySum =xxxxxx
导入:import{同名导出变量1,同名导出变量2} from’模块名或路径’
如何选择:如果按需加载少量的,用命名导入导出
如果要全部加载,用默认导入导出
包
将模块,代码,其他资料聚合成一个文件夹,就是包
所有包的根目录里面必须有package.json文件(也叫清单文件,记录包的清单信息)
如:有一个utils文件夹下面有各种.js和.json等文件,就管这个utils文件夹叫包
package.json文件常用配置项:
{
“name”: “cz_utils”, //软件包名称
“version”: “1.0.0”, //软件包当前版本号
“description”: “一个数组和字符串常用工具方法的包”, //软件包简短描述
“main”: “index.js”, //软件包入口点
“author”: “itheima”, //软件包作者
“license”: “MIT” //软件包许可证(商用后可以用作者名字宣传)
}
包分类:
项目包:用于编写项目和业务逻辑
软件包:封装工具和方法进行使用(如utils文件夹)
注意:导入软件包时,引入的默认是indexjs 模块文件/main 属性指定的模块文件
本地软件包:当前项目内使用,封装属性和方法,存在于node modules
全局软件包(nodemon):本机所有项目使用,封装命令和工具,存在于系统设置的位置
软件包结构
utils文件夹下有lib工具模块文件夹,index.js,package.json
lib工具模块文件夹下有arr.js,str.js
lib文件夹下是软件包里要封装的工具和方法的源代码
index.js文件是默认向外暴露的唯一出口,把所有工具模块下的方法集中起来,统一向外暴露
package.json是软件包的说明清单文件
node.js软件包入门例子中arr.js,str.js用默认导出,index.js中引入,再统一导出
和utils文件夹同级的server.js文件导入index.js统一导出的属性和方法
npm软件包管理器
是别人帮我们写好了各种工具的软件包,相当于已经写好了各种功能的各种函数,我们只要通过对应名字用就可以了
npm使用
下载不成功的话用管理员启动vscode
右键项目文件夹在终端输入命令:
1.初始化清单文件:npm init -y 得到package.json文件,用来记录当前项目已经下载了哪些软件包(如果项目已经有了这个文件那么跳过1,-y表示都是默认的意思)
2.下载软件包:npm i 软件包名称 (npm管理器帮你找到对应的软件包下载到当前项目
3.使用软件包(下载的软件包导入时候输入名字即可,不用路径导入)
在进行2操作后,package.json文件会记录你下载过的软件包和对应版本号
在进行2操作后,项目文件夹下会生成一个node_modules的文件夹,里面放着你下载的软件包们
在进行2操作后,项目文件夹下还会生成package-lock.json文件,用于锁定版本号
npm安装所有依赖
比如你搬运的代码或拿到的项目有npm的一些软件包,但是你没下载,缺少node_modules的文件夹,现在只有package-lock.json,package.json,server.js,无法正常运行,缺少本地软件包
那么要自己用npm下载以来
方法:在项目终端输入命令:npm i
会自动下载package.json中记录的所有软件包到node_modules文件夹,这个文件夹内容的下载比磁盘传递的速度要快得多
全局软件包nodemon
本地软件包:当前项目内使用,封装属性和方法,存在于node modules
全局软件包:本机所有项目使用,封装命令和工具,存在于系统设置的位置
nodemon作用:代替node命令,检测代码更改,自动重启程序
使用:
1.安装:npm i nodemon -g(-g代表安装到全局环境中)
2.运行:nodemon 待执行的目标js文件
(P96里评论说:系统禁止运行脚本的话可以换一个命令 npx nodemon run dev,但npx好像是临时的,不是下载后还能用的;也有说连外网就好下了的)
常用命令
功能-命令
执行 js 文件:node xxx
初始化 package.json:npm init -y
下载本地软件包:npm i 软件包名
下载全局软件包:npm i 软件包名 -g
删除软件包:npm uni 软件包名