思考:?javascript能否做后端开发
可以需要借助nodejs==>node也是运行环境
什么是nodejs?
Node.js是一个基于Chrome V8引擎的javascript运行环境
1.浏览器是Javascript的前端运行环境 2.Node.js是Javascript的后端运行环境 3.Node.js中无法调用DOM和BOM等浏览器内置API
3.Node.js安装
LTS和Current
4.什么是终端?
终端(Terminal) 是专门为开发人员设计的,用于实现人机交互的一种方式
5.什么是fs文件系统模块
fs模块是Node.js官方提供的 用来操作文件的模块,它提供了一系列的方法和属性,用来满足用户对文件的操作需求
例如:fs.readFile(),用啦读取指定文件中的内容
fs.readFile(path,[ options],callback)
参数一:必选参数,字符串,表示文件的路径
参数二:可选参数,表示以什么编码格式来读取文件
参数三:必选参数,文件读取完成后,通过回调函数拿到读取的结果.
5.1利用fs来读文件整理后保存在新的文件中
5.1.1使用fs.readFile方法来读取并整理文件
fs.readFile(__dirname+"/成绩.txt","utf8",(err,dataStr)=>{
if(!err){
.....(整理数据)
var str = (整理后的数据)
}
})
5.1.2 写入文件,使用fs.writeFile方法
fs.writeFile("./整理后的成绩.txt",str,(err)=>{
if(!err){
log("写入成功")
}else{
log("写入失败")
}
})
6.什么是path路径模块
path路径模块是Nodejs官方提供的,用来处理路径的模块,它提供了一系列的方法和属性
例如:
path.join()方法,用来将多个路径片段拼接成一个完整的路径字符串
path.basename()方法,用来从路径中字符串中,将文件名解析出来
1.path.join([..paths])
返回值:<string> ==>拼接的路径字符串
let str = path.join("/a","./b/c","../../","/e")
//../ 会抵消前面一个路径,两个会抵消前面两个路径
log(str) //输出为 \a\e
1.2在读取文件时,也可以使用join方法,进行读取
fs.readFile(path.join(__dirname,"/2.txt"),...)
2.path.basename(xx,[后缀名]) //可将文件名提取出来,如果不写第二个参数,则连同后缀名一起提取出来
var fpath = "/a/b/c/index.html"
const lastName = path.basename(fpath,".html")
3.path.extname(xx) //可获取路径中的扩展名部分
const extName = path.extname(fpath)
log(extName) //输出 .html
时钟案例的两个注意点:
1.fs.writeFile()方法只能用来创建文件,不能用来创建路径
2.当重复调用writeFile()方法写入同一个文件,新的内容会覆盖掉旧的内容
什么是http模块?
回顾:什么是客户端,什么是服务器?
在网络节点中,负责消费资源的电脑,就是客户端;负责对外提供网络资源的电脑,叫做服务器
http模块是Node.js官方提供的 用来创建web服务器的模块,通过http模块提供的http.createServer()方法,就能方便的把一台普通的电脑,变成一台web服务器,从而对外提供web资源服务.
模块化
1.能够说出模块化的好处
2.能够知道CommonJS规定了哪些内容
3.能够说出Node.js中模块的三大分类各自是什么?
4.能够使用npm管理包
5.能够了解什么是模块化管理机制
6.能够了解什么是模块化规范的结构
7.能够了解模块化的加载机制
什么是模块化?
模块化是指解决一个复杂问题时,自顶向下把系统划分成若干模块的过程,对于整个系统来说,模块是可组合,可分解和更换的单元
模块化拆分的好处:
1.提高了代码的可复用性
2.提高了代码的可维护性
3.可以实现按需加载
能够说出Node.js中模块的三大分类各自是什么?
1.内置模块
2.自定义模块
3.第三方模块
1.使用强大require()方法,可以加载需要的模块
加载内置模块 const fs = require("fs)
加载自定义模块 const custom = require('./custom.js')
加载第三方模块 const moment = require('moment')
什么是模块作用域?
和函数作用域类似,在自定义模块中定义的变量 方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域
module对象
在每个js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息,例如path exports...
使用require()时,得到的永远以module.exports指向的对象为准
Node.js中的模块化规范
Node.js遵循了CommonJS的模块化规范,CommonJS规定了模块的特性喝各模块之间如何相互依赖
包都是内置模块封装出来的
包的版本是以点分十进制形式进行定义的,总共有三位数字,例如2.24.0
第一位数字:大版本
第二位数字:功能版本
第三位数字:Bug修复版本
版本序号的规则:只要前面的版本号增长了,则后面的版本号归零
包管理配置文件 必须提供一个叫做package.json的包管理配置文件,用来记录与项目有关的一些配置信息.
如何从项目中卸载包:
npm uninstall 包名,会自动从package.json的dependencies中移除掉
devDependencies
在项目上线之后不会用到,则建议把这些包记录到devDependencies节点中
切换npm 的下包镜像源
下包的镜像源,指的是下包的服务器地址
//查看当前的下包镜镜像源
1.npm config get registry
//将下包尔达镜像源切换为淘宝镜像源
2.npm config set registry=https://registry.npm.taobao.org/
//检查镜像源是否下载成功
3.npm config get registry
全局安装nrm
npm i nrm -g
//查看所有可用的镜像源
nrm ls
//将下包的镜像源切换为淘宝 镜像
nrm use taobao
项目包
项目包被分为两类
开发依赖包:(被记录到denDependencies节点中的包,只会在开发期间会用到)
核心依赖包(被记录到dependecies节点中娥包,在开发期间的项目上线之后都会用到)
i5ting_toc
i5ting_toc是一个可以把md文档转换为html页面的小工具,使用步骤如下:
npm i -g i5ting_toc
i5ting_toc -f 要转换的md文档路径 -o
npm unpublish 包名 --force
npm unpublish 命令只能删除72小时之内发布的包
npm unpublish 删除的包 在24小时之内不能再重新发布
什么是Express?
Express是基于node.js平台,快速 开放 极简的Web开发框架
Express与node的内置模块类似,用于创建服务器
1.不使用Express能否创建Web服务器?
可以,使用node.js提供的原生http模块即可
2.有了http模块,为什么还要用Express?
http内置模块用起来很复杂,Express是基于内置的http模块进一步封装起来的,能够极大的提高开发效率
Express路由的匹配过程
语法: app.method(url,function)
注意点:1.按照定义的先后顺序进行匹配
2.请求类型和请求的url同时匹配成功,才会调用对应的处理函数
中间件的格式
格式===> app.method(url,function(req,res,next){
next()
})
中间件的函数形参列表中,必须包含next参数,而路由处理函数中只包含req和res
** next函数的作用:
next()表示转交给下一个中间件或下一个路由
中间件的作用
多个中间件之间,共享一份req和res,基于这样的特性,我们可以在上游的中间件中,统一为req和res对象添加自定义的属性和方法,供下游的中间件或路由进行使用
***定义多个全局中间件
可以使用app.use()连续定义多个全局中间件,客户端请求到达服务器后,会按照定义的相互顺序依次进行调用,
例如:
app.use()
app.use()
app.use()
...
Express局部中间件组件
不使用app.use()定义的中间件,叫做局部生效的中间件,示例代码如下:
const mw = function(req.res.next){next()}
app.get("/",mw,(req.res)=>{
res.send({"name":"zqk"})
})
//也可以使用多个局部中间件
app.get(url,mw,mw1,mw2,...,(req.res)=>{})
//或使用一个数组包起来也可以
中间件的5个使用注意事项
1.一定要在路由之前注册中间件
2.客户端发送过来的请求,可以连续调用多个中间件进行处理
3.执行完中间件的业务代码之后,不要忘记调用next()函数
4.为了防止代码逻辑混乱,调用next()函数后不要再写额外的代码
5.连续调用多个中间件时,多个中间件之间,共享req和res对象
错误级别的中间件
**注意:一定要放在所有的路由之后
实例: app.use((err,req,res,next)=>{
console.log("发生了错误!"+err.message)
res.send("Error:"+err.message)
})
cors跨域资源共享
1.简单请求
同时满足以下两个条件
1.请求方式:get post head三者之中
2.http头部信息不超过以下几种字段:无自定义头部字段,Accept...
2.预检请求:
1.请求方式为get post head之外的请求类型
2.请求头中包含自定义头部字段
3.向服务器发送了application/json格式的数据
在这些里面符合任意一个条件的请求,都会先发送一个options请求进行预检,以获得是否允许该实际请求,所以这次options请求被称为预检请求.
解决跨域问题
1.首先引入cors中间件,从而解决接口跨域问题
2.一定要在路由之前配置cors中间件 例如模块化开发,使用路由来设置模块化
const router = require("./module")
const cors = require("cors")
...
app.use(express.json()) //解析json格式数据
app.use(express.urlencoded({extended:false})) //解析urlencoded数据
app.use(cors) //注册跨域设置
app.use("/route",router) //注册路由
app.listen(3000,()=>{
log("服务器已经启动")
})
2.在前端请求进行访问
axios({
method:"get",
url:"127.0.0.1:3000/route",
params:{
id:8,
name:"zqk"
}
}).then((value)=>{
log(value.data)
},()=>{})
//由于解决了跨域问题,所以在请求将不会报错,并且可以请求得到.
路径拼接问题(node ./xxx/index.js容易出现的问题)
在使用node ./xxx/index.js 来运行这个js时,若在你的代码中有reaFile("./x.txt")时,会在你运行node这个目录下进行./寻找,就会报错(因为你写的./是在index.js下写的)
解决办法:
1.可以提供一个完整的文件存放路径(readFile("完整路径")
需要用\\来转义
路径=> D:\\APPDATA1\\...\\..\\index.js
设置cors响应头
在响应头中,你可以指定哪些域可以访问你这个服务器,并且可以设置请求头 请求的方法设置等
app.get("/user",(req,res)=>{
1.res.setHeader("Access-Control-Allow-Origin","*") //允许任意域访问
2.res.setHeader("Access-Control-Allow-Headers","Content-Type","X-Custom-Header")客户端仅限于向服务器发送9个请求头如果想发送额外的请求,则需要在服务器设置额外的请求头进行声明
})
3.res.setHeader("Access-Control-Allow-Methods","POST ,GET, DELETE, HEAD") //cors仅支持客户端发起GET POST HEAD请求,如何想用别的请求,则需要在响应头部设置请求方法
//允许所有的http请求方法
res.setHeader("Access-Control-Allow-Methods","*")
将整个html时钟页面拆分成三个分页面
1.设置正则规则
const regStyle = /<style>[\s\S]*<\/style>/ //匹配在style里的所有的空白字符,非空白字符
const regScript = /<script>[\s\S]*<\/script>/ //匹配在cript里的所有的空白字符,非空白字符
const regHtml = ...
2.分别定义三个函数,用来匹配到自己相应的结果后,分别将结果写入对应的文件内,
function resolveCss(value){
//exec=>将匹配的结果返回一个数组,数组的索引0就是其结果
const cssTest = regStyle.exec(value)
let newCss = cssTest[0].replace(""<style>","").replace(""</style>","") //将两个style去掉,因为在css文件中,不能出现style标签
fs.writeFile(__dirname+"./clock/index.css",newCss,(err)=>{
if(!err){
log("写入成功")
}
})
}
function resolveJS....
function resolveHtml...
3.在读取文件时,将其三个方法调用即可
fs.readFile("./index.html",(err,dataStr)=>{
if(!err){
resolveCss(dataStr)
resolveJS(dataStr)
resolveHtml(dataStr)
}
})
自定义格式时间
1.在模块(index)中定义一个函数
function dateFormat(value){
const dt = new Date(value)
const y = dt.getFullYear() //获取年份
const m = padZero(dt.getMonth()+1)//获取年份
const d = padZero(dt.getDate())//获取日期
const hh = padZero(dt.getHours()) //获取小时
const mm = padZero(dt.getMinutes()) //获取分钟
const ss = padZero(dt.getSeconds()) //获取秒数
return `${}-${}-${}-${}:${}`
}
//定义补零函数,比如2022-9-1=>2022-09-01
function padZero(value){
return value>9? value:"0"+value
}
module.exports = dateFormat
2.在test.js中引入模块
const time = require("./index")
const dt = Date.now() //获取当前时间 例:1647178555673
const newTime = time.dateFormat(dt)
log("newTime") //例输出为:2022-03-13-21:35:06