node.js基础
🍓什么是node.js
- 定义:
node.js
是一个基于Chrome V8
引擎的JavaScript
运行环境(后端javaScript
运行环境)
浏览器属于JavaScript
前端运行环境 node.js
官网:https://nodejs.org/en
🍓node.js模块
-
📌引入模块的方式
js//引入fs模块(内置模块和三方模块需要写上模块名) const fs = require('fs') //引入自定义模块(自定义模块需要写上js路径) const dataFormat = require('./dataFormat.js')
-
📌模块分类
- 🍁内置模块:
fs、path、http
- 🍁自定义模块:
用户创建的每一个js
文件,引用自定义模块,需要通过相对路径使用 - 🍁第三方模块
- 🍁内置模块:
-
📌模块作用域
在模块中定义的全局变量var
,作用域只在模块自己内部,可以解决全局变量被污染的问题 -
📌向外暴露模块作用域的成员:
每一个.js
自定义模块中都有一个module
对象,module
对象中的成员exports
对象用来对外暴露模块作用域中的成员
🍒🍒 内置模块
🍅🍅🍅fs模块
引入fs
内置模块
js
const fs = require('fs')
-
📌
fs
模块用于操作文件 -
📌
fs.readFile(path[, options], callback)
读取文件- 🍁
path
:必选参数,文件路径-字符串 - 🍁
options
:可选参数,编码格式 - 🍁
callback
:必选参数,文件读取成功的回调函数
形参:- 🌷
err
:失败的结果 - 🌷
dataStr
:成功的结果
- 🌷
jsfs.readFile('C:\\Users\\Desktop\\abc.txt', 'utf8', (err, dataStr) => { if(!err) { console.log(dataStr); } else { console.error(err) } });
- 🍁
-
📌
fs.writeFile(path, data[, options], callback)
写文件- 🍁
path
:必选参数,文件路径-字符串 - 🍁
data
: 必选参数,写入内容 - 🍁
options
:可选参数,编码格式 - 🍁
callback
:必选参数,文件编写成功的回调函数
形参:- 🌷
err
:失败的结果
- 🌷
jsfs.writeFile('C:\\Users\\Desktop\\1.txt', "你好,nodejs", 'utf8', err => { if(err) { console.log(err) } })
- 🍁
-
📌
fs.mkdir(path[, options], callback )
创建目录- 🍁
path
:必选参数 - 🍁
options
:可选参数(对象)- 🌷
recursive
:
true
:递归创建
false
:不会递归创建
- 🌷
- 🍁
callback
:必选参数,文件夹创建成功的回调函数
形参:- 🌷
err
:失败的结果 - 🌷
path
:文件夹路径,返回创建的第一层级的目录
- 🌷
- 🍁
-
📌
fs.rmdir(path[, options], callback )
删除目录- 🍁
path
:必选参数 - 🍁
options
:可选参数(对象)- 🌷
recursive
:
true
:递归删除
false
:不会递归删除
- 🌷
- 🍁callback:必选参数,文件夹删除成功的回调函数
形参:- 🌷
err
:失败的结果 - 🌷
path
:文件夹路径,返回创建的第一层级的目录
- 🌷
- 🍁
-
📌
fs.unlink(path, callback)
删除文件- 🍁
path
:必选参数 - 🍁
callback
:必选参数,文件删除成功的回调函数
形参:- 🌷
err
:失败的结果
- 🌷
- 🍁
🍅🍅🍅path模块
路径问题 :nodejs
执行js
时,js
中的相对路径是参照node
命令执行所在的目录,而不是参照js
文件所在的目录
- 📌使用绝对路径(不推荐)
缺点:
移植性非常差,不利于维护 - 📌
__dirname
:代表当前文件所处的目录(不推荐)
缺点:- 🍁路径需要通过拼接的形式生成
- 🍁只能处理当前目录以下的文件,当前目录之前的文件无法处理
- 📌
path
模块(推荐)
引入path
内置模块
js
const path = require('path')
const pathStr = path.join('/a','/b/c','../','./d','e')
console.log(pathStr) //\a\b\d\e
const fpath = '\a\b\v\index.html';
console.log(path.basename(fpath)) //index.html
console.log(path.basename(fpath, '.html')) //index
console.log(path.extname(fpath)) //.html
- 🍁
join(path0,path1,path2...,pathn)
:拼接多个路径,一个../
消除一个前面的路径 - 🍁
basename(path[, ext])
:获取文件名称 - 🍁
extname(path)
:获取文件的扩展名
🍅🍅🍅http模块
引入http
模块
js
const http = require('http')
-
📌
http
模块用于创建web
服务 -
📌创建
http
服务- 🍁引入
http
模块 - 🍁创建
web
服务器实例 - 🍁为服务器绑定
request
事件,监听客户端的请求 - 🍁启动服务器
js//1. 引入http模块 const http = require('http') //2. 创建web服务器实例 const server = http.createServer() //3. 为服务器绑定request事件,监听客户端的请求 server.on('request', function(req, res){ const url = req.url const method = req.method console.log(`Your request url is ${url}, and request method is ${method}`) res.setHeader('Content-Type', 'text/html;charset=utf-8') res.end('你好,nodejs') }) //4. 启动服务器 server.listen('8080', ()=>{ console.log('server is runnging at http://127.0.0.1:8080') })
- 🍁引入
-
📌
request
事件回调函数- 🍁
req
:- 🌷
req.url
:获取请求路径 - 🌷
req.method
:获取请求方式
- 🌷
- 🍁
res
:- 🌷
res.end(str)
:结束本次请求,并向客户端发送指定内容 - 🌷
res.setHeader(key, val)
: 设置响应头
- 🌷
- 🍁
🍒🍒自定义模块
node.js
中,自定义模块暴露成员通过挂载在module.exports
对象上,其中exports
对象默认也是内存地址指向module.exports
,只要在挂载的时候没有更改module.exports
对象的地址或者更改exports
对象的地址就不会有问题。
js
//挂载属性
module.exports.name = '张三'
//挂载方法
module.exports.sayHello = () => {
console.log('Hello world!')
}
//挂载属性
exports.age = 23
//注意:该方式修改了module.exports对象内存地址的指向,导致module.exports和exports指向的不是同一个地址,则exports挂载属性不会生效。
module.exports = {
code:'0000',
message:'成功!'
}
//注意:该方式修改了exports对象内存地址的指向,导致module.exports和exports指向的不是同一个地址,则exports挂载属性不会生效。
exports = {
title:'爱好',
content:'足球'
}
🍒🍒第三方模块
🍅🍅🍅npm
npm
用于下载发布管理三方包,我们可以通过npm
命令去下载安装一些三方包供我们项目使用
查询包:https://www.npmjs.com/
下载包:https://registry.npmjs.org/
node_modules
是用于存放三方依赖的文件夹package.json
用于记录项目中使用的包,通过执行命令npm i
来初始化项目,安装三方包
🍅🍅🍅包的分类
- 📌项目包
- 🍁定义:那些被安装到项目的
node_modules
目录中的包,被称为项目包 - 🍁开发依赖包
npm i {packageName} -D
被记录到package.json
文件中节点devDependencies
下面的包被称为开发依赖包,只在开发期间会使用到 - 🍁核心依赖包
npm i {packageName}
被记录到package.json
文件中节点dependencies
下面的包被称为核心依赖包,开发期间和项目上线后都会使用到
- 🍁定义:那些被安装到项目的
- 📌全局包
- 🍁安装全局包:
npm i {packageName} -g
- 🍁卸载全局包:
npm uninstall {packageName} -g
- 🍁全局依赖包会下载到
C:\Users\用户目录\AppData\Roaming\npm\node_modules
- 🍁注意:
只有工具性质的包,才有全局安装的必要性,因为它们提供了好用的终端命令(一般官方文档里面会告诉你)
- 🍁安装全局包:
🍅🍅🍅规范包的组成结构
- 包必须以单独的目录而存在
- 包的顶级目录下必须包含
package.json
文件 package.json
必须包含name、version、main
这三个属性,分别代表包名、包版本、包的入口
🍅🍅🍅发布自己的包
-
📌在
package.json
中编写自己的包信息json{ "name":"{packageName}", //必须与当前npm仓库中的包名不重名 "version":"1.0.0", //版本号 "main":"index.js", //包程序入口 "description":"包的描述信息", "keywords":["","",""...] //检索包的关键字信息 "license":"ISC" //开源许可协议 }
-
📌编写
README.MD
文档,写明使用此包的方式 -
📌注册
npm
账号
https://www.npmjs.com/
-
📌在终端输入以下命令,登录
npm
账号(在此之前,一定要先把下包的镜像地址切换到npm
官方服务器)
npm login
-
📌在包的根目录下输入以下命令,即可发布包
npm publish
🍅🍅🍅express
express
是基于内置模块http
的基础上封装的一套可以方便、快速的创建Web
网站服务器或API
接口服务器
安装
npm i express
🍓🍅🍅🍅express创建
web服务器的步骤
-
📌引入
express
模块 -
📌创建
web
服务器 -
📌启动
web
服务,监听端口jsconst express = require('express') //创建web服务器 const app = express() //启动web服务,监听端口 app.listen('80', ()=>{ console.log('express server running at http://127.0.0.1') })
🍓🍅🍅🍅挂载路由
app.get(url, function)
app.post(url, function)
🍓🍅🍅🍅req获取请求参数
-
📌获取
url
地址传参:(形如:http://127.0.0.1/user?name=张三&age=23
)
req.query.{key}
-
📌获取动态地址传参:(形如:
http://127.0.0.1/query/1234
)
req.params.{key}
-
📌获取请求体数据
req.body(需要配置解析请求体数据的中间件)
jsapp.get('/user', function(req, res) { console.log('进入GET /user') //req.query 获取url地址传参(http://127.0.0.1/user?name=张三&age=23) const name = req.query.name const age = req.query.age //向客户端响应内容 res.send({name, age}) }) app.get('/query/:id/:name',(req, res) => { //req.params 获取url地址的动态参数(http://127.0.0.1/query/1234/张三) const id = req.params.id const name = req.params.name res.send({id, name}) }) //express.urlencoded({extended:false}) //express.json() app.post('/add/user', express.json(), (req, res) => { console.log(req.body) res.send(req.body) })
🍓🍅🍅🍅app.use()函数
- 📌挂载静态资源:
app.use(express.static({static_path}))
app.use('{地址前缀}', express.static({static_path}))
- 📌路由模块化:
app.use(模块路由)
app.use({地址前缀}, 模块路由)
- 📌注册中间件
app.use({中间件名称})
🍓🍅🍅🍅路由模块化:
问题: 通过app
去挂载路由,会导致js
文件臃肿,难以维护,路由模块化可以解决这个问题
-
📌引入
express
模块 -
📌创建路由对象
-
📌挂载路由
-
📌暴露路由对象
-
📌
app.use()
注册路由对象js//引入express模块 const express = require('express') //创建路由对象 const router = express.Router() router.get('/user/list', (req, res) => { res.send([{name:'张三',age:23},{name:'李四', age:24}]) }) //暴露路由(注意:这里不能使用exports = router) module.exports = router //注册路由 const xxx = require('./xxx.js') app.use(xxx)
🍓🍅🍅🍅中间件
🍒🍒🍅🍅🍅定义中间件
js
//普通中间件
const mw = function(req, res, next){
//放行
next()
}
//错误中间件
const mw = function(err, req, res, next){
//放行
next()
}
🍒🍒🍅🍅🍅注册中间件
-
📌全局中间件注册:
app.use(mw)
-
📌单个局部中间件注册:
app.get(url, 中间件, 函数)
-
📌多个局部中间件注册:
app.get(url, [中间件1, 中间件2, ..., 中间件n], 函数)
js//定义全局中间件 const mw = function(req, res, next){ console.log('最简单的中间件函数') //流转给后面的路由 next() } //注册全局中间件 app.use(mw) //定义中间件 const mv2 = function(req, res, next){ console.log('最简单的中间件函数2') next() } //挂载路由,监听客户端post请求,请求地址是/user //将中间件mv2注册为局部中间件 app.post('/user', mv2, function(req, res){ console.log('进入POST /user') throw new Error('服务器内部发生了错误!') res.send({code:'000000', msg:'请求失败!'}) }) //定义中间件 const mv3 = function(req, res, next){ console.log('最简单的中间件函数3') next() } //挂载路由,监听客户端动态地址传参 //注册多个局部中间件 app.get('/query/:id/:name', [mv2, mv3],(req, res) => { //req.params 获取url地址的动态参数(http://127.0.0.1/query/1234) const id = req.params.id const name = req.params.name res.send({id, name}) })
-
📌多个中间件之间,共享同一份
req
和res
,我们可以在上游的中间件中为req
和res
挂载某些属性和方法为下游中间件使用
调用顺序:(与中间件注册的顺序有关)
客户端请求 => 中间件1 => 中间件2 => 中间件3 => ... => 中间件n => 响应客户端
🍒🍒🍅🍅🍅中间件的分类
-
📌应用级别的中间件
通过app.use()、app.get()、app.post()
绑定的 -
📌路由级别的中间件
通过router.use()、router.get()、router.post()
绑定的 -
📌错误级别的中间件(注意:错误的中间件一定要放在最后定义)
app.use(function(err, req, res, next))
js//挂载路由,监听客户端post请求,请求地址是/user //将中间件mv2注册为局部中间件 app.post('/user', mv2, function(req, res){ console.log('进入POST /user') throw new Error('服务器内部发生了错误!') res.send({code:'000000', msg:'请求失败!'}) }) //定义全局错误中间件 app.use(function(err, req, res, next){ console.log('发生了错误:' + err.message) res.send(err.message) })
-
📌
Express
内置的中间件
配置解析application/json
格式请求体数据的内置中间件
app.use(express.json())
配置解析application/x-www-form-urlencoded
格式请求体数据的内置中间件
app.use(express.urlencoded({extended:false}))
由于express
解析请求体数据中间件在4.16.0
之后才支持,在此版本之前使用body-parser
中间件解析请求体- 🍁下载
body-parser
npm install body-parser
- 🍁引入
body-parser
模块 - 🍁调用
app.use()
注册中间件
app.use(parser.json())
app.use(parser.urlencoded({extended:false}))
- 🍁下载
🍒🍒🍅🍅🍅中间件解决跨域问题
- 📌安装
cors
中间件
npm i cors
- 📌注册
cors
中间件为全局中间件
app.use(cors())
- 📌
cors
相关的响应头- 🍁
Access-Control-Allow-Origin:*|具体的http地址
- 🌷
*
:允许任何请求访问 - 🌷具体的http地址:如
http://app.cn.nb:81
,表示只允许这个ip
开头的客户端可以访问
- 🌷
- 🍁
Access-Control-Allow-Headers
- 🌷允许客户端发送的请求头
- 🌷默认情况下,
cors
仅支持客户端发送如下的请求头:
Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width、Content-Type
(值仅限于text/plain、multipart/form-data、application/x-www-form-urlencoded
)
- 🍁
Access-Control-Allow-Methods
默认情况下,cors
仅支持客户端发起GET、PUT、HEAD
请求
- 🍁
🍓node.js常用命令
shell
# 1. node版本查看
node -v
# 2. 运行javaScript脚本
node xxx.js
# 3. npm版本查看
npm -v
# 4. 安装下载包(默认下载最新版本)
npm install {packageName}
npm i {packageName}
# 5. 安装下载包(指定下载版本)
npm install {packageName}@{version}
npm i {packageName}@{version}
# 6. 初始化项目,根据package.json安装三方包
npm install
npm i
# 7. 卸载包
npm uninstall {packageName}
# 8. 创建package.json
npm init -y
# 9. 安装下载开发环境的包
npm i {packageName} -D
npm i {packageName} --save-dev
# 10. 检查当前下包镜像源
npm config get registry
# 11. 切换下包镜像源
npm config set registry=https://registry.npm.taobao.org/
# 12. 使用nrm快速切换镜像源
## 12.1. 下载安装nrm,将nrm安装成全局可用的工具
npm i nrm -g
## 12.2. 查看所有可用的镜像源
nrm ls
## 12.3. 将下载的镜像源切换为taobao镜像
nrm use taobao
# 13. 安装全局包
npm i {packageName} -g
# 14. 卸载全局包
npm uninstall {packageName} -g
# 15. 登录npm账号
npm login
# 16. 发布包(包根目录下执行)
npm publish
# 17. md文件转html
## 17.1 下载安装i5ting_toc,将i5ting_toc安装成全局可用的工具
npm i i5ting_toc -g
## 17.2 md文件转html
i5ting_toc -f xxx.md -o