win +r 打开终端 cd 目录名 进入到指定的目录 md 目录名 创建一个文件夹
dir 列出当前目录下的所有文件 rd 目录名 删除一个文件夹 node -v查看node版本
cd 路径 (切换到某路径) node js文件 (用node执行js文件)
在文件夹内直接按shift+鼠标右键点击在此处打开Powershell窗口可以自动定位到该文件夹
.终端中的快捷键:
在 Windows 的 powershell 或 cmd 终端中,我们可以通过如下快捷键,来提高终端的操作效率:
① 使用 ↑ 键,可以快速定位到上一次执行的命令
② 使用 tab 键,能够快速补全路径
③ 使用 esc 键,能够快速清空当前已输入的命令
④ 输入 cls 命令,可以清空终端
在node中有一个全局对象global,它的作用和网页中的window类似
在全局中创建的变量和函数都会作为global的属性或方法保存
当node在执行模块中的代码时,他会首先在代码的最顶部,添加如下代码:
function(exports,require,module,__filename,__dirname){
在代码最底部,添加如下代码:
}
实际上模块中的代码都是包装在一个函数中执行的,并在函数执行时,同时传入了5个参数
exports:该对象用来将变量或函数暴露到外部
require:函数,用来引入外部模块
module:代表的是当前模块本身,exports就是module的属性,既可以用exports导出,也可以用module.exports导出
__filename:当前模块的完整路径
__dirname:当前模块所在文件夹的完整路径
arguments.callee:这个属性保存的就是当前执行的函数
--------------------------------------------------------------------------------------------------------------------------------
fs 文件系统模块:
fs 模块是 Node.js 官方提供的、用来操作文件的模块。
fs.readFile() 方法,用来读取指定文件中的内容
fs.writeFile() 方法,用来向指定的文件中写入内容
读取文件:
const fs=require("fs") //导入fs模块,来操作文件
//调用fs.readFile()方式读取文件
fs.readFile("文件路径","以什么格式读取内容,默认utf8(可选)",function(err,dataStr){
//err表示读取失败的结果,dataStr读取成功的结果
//如果读取成功err为null,dataStr为读取文件结果
//如果读取失败err为错误对象,dataStr为undefined
if(err){
console.log("读取失败",err.message) //判断文件是否读取成功
}else{
console.log("读取成功"+dataStr)
}
})
写入文件:
const fs=require("fs") //导入fs模块,来操作文件
//调用fs.writeFile()方法写入内容
fs.writeFile("内容存放路径","要写入的内容","以什么格式写入内容,默认utf8(可选)",function(err){
//如果写入成功,则err为null
//如写入失败err为错误对象
if(err){
console.log("写入失败"+err.message)
}else{ //判断是否写入成功
console.log("写入成功")
}
})
fs 模块 - 路径动态拼接的问题:
在使用 fs 模块操作文件时,如果提供的操作路径是以 ./ 或 ../ 开头的相对路径时,很容易出现路径动态拼接错误的问题。
原因:代码在运行的时候,会以执行 node 命令时所处的目录,动态拼接出被操作文件的完整路径。
解决方案:1.使用完整路径(不建议) 2.使用path.join()路径拼接
--------------------------------------------------------------------------------------------------------------------------------
path 路径模块 :
path 模块是 Node.js 官方提供的、用来处理路径的模块
path.join() 方法,用来将多个路径片段拼接成一个完整的路径字符串:
const path=require("path") //导入path模块
var a=path.join("/a","/b/c","../","./d","e")
console.log(a) //输出\a\b\d\e ../可以抵消一个路径
-------------------------------------------------------
const fs = require("fs"); //导入fs模块
const path=require("path") //导入path模块
//__dirname表示当前路径
fs.readFile(path.join(__dirname,"要读取的路径"), function (err,datastr) {
if (err) {
console.log("读取失败" + err.message);
} else{
console.log("成功"+datastr)
}
});
//今后凡是涉及到路径拼接的操作,都要使用 path.join() 方法进行处理。不要直接使用 + 进行字符串的拼接
path.basename()方法
使用 path.basename() 方法,可以获取路径中最后一部分,经常通过这个方法获取路径中的文件名
//语法 path.basename("文件路径","文件扩展名(可选)")
---------------------------------------------------
const path=require("path")
var a="/a/b/c/index.html"
var b=path.basename(a)
console.log(b) //index.html 不写第二个参数会把最后部分返回
var c=path.basename(b,".html")
console.log(c)//index 写第二个参数会把扩展名删掉只保留文件名
path.extname()方法:
使用 path.extname() 方法,可以获取路径中的扩展名部分
const path=require("path")
var a="/a/b/c/index.html"
var b=path.extname(a)
console.log(b)//.html
--------------------------------------------------------------------------------------------------------------------------------
http 模块:
http 模块是 Node.js 官方提供的、用来创建 web 服务器的模块。通过 http 模块提供的 http.createServer() 方法,就 能方便的把一台普通的电脑,变成一台 Web 服务器,从而对外提供 Web 资源服务。
IP 地址 :
① 互联网中每台 Web 服务器,都有自己的 IP 地址,例如:大家可以在 Windows 的终端中运行 ping www.baidu.com 命 令,即可查看到百度服务器的 IP 地址。
② 在开发期间,自己的电脑既是一台服务器,也是一个客户端,为了方便测试,可以在自己的浏览器中输入 127.0.0.1 这个 IP 地址,就能把自己的电脑当做一台服务器进行访问了。
在开发测试期间, 127.0.0.1 对应的域名是 localhost,它们都代表我们自己的这台电脑,在使用效果上没有任何区别。
端口号 :
在一台电脑中,可以运行成百上千个 web 服务。每个 web 服务都对应一个唯一的端口号。客户端发送过来的 网络请求,通过端口号,可以被准确地交给对应的 web 服务进行处理。
注意: ① 每个端口号不能同时被多个 web 服务占用。
② 在实际应用中,URL 中的 80 端口可以被省略
创建最基本的 web 服务器:
const http=require("http") //导入http模块
const server=http.createServer() //调用 http.createServer()方法创建web服务器实例
server.on("request",(req,res)=>{ //使用服务器实例.on()方法为服务器实例绑定request事件,监听客户端的请求
//只要有客户端来请求此服务器,就会触发request事件,调用这个事件处理函数
//req是请求对象,它包含了与客户端相关的数据和属性
//req.url是客户端请求的url地址
//req.method是客户端的method请求类型
//res是响应对象,它包含了与服务器相关的数据和属性
//res.end()方法可以向客户端发送指定内容,并结束这次请求的处理过程
console.log(req.method) //输出Get
console.log(req.url) // 输出/
res.setHeader("content-type","text/html;charset=utf-8") //解决中文乱码问题
res.end("哈哈哈") //打开http://127.0.0.1页面后显示哈哈哈
})
server.listen(80,()=>{ //调用server.listen(端口号,回调)方法,启动web服务器
console.log("http://127.0.0.1")
})
---------------------------------------------------------------------------------------------------------------------------------
模块化 :
Node.js 中根据模块来源的不同,将模块分为了 3 大类分别是:
内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http 等)
自定义模块(用户创建的每个 .js 文件,都是自定义模块)
第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载
加载模块 :
//使用require()加载方法
const fs=require("fs")//加载内置fs模块
const index=require("./index.js")//加载自定义的模块
const moment=require("moment")//加载第三方模块
//注意:使用 require() 方法加载其它模块时,会执行被加载模块中的代码
向外共享模块中的成员 :
//a.js文件
exports.name="小王"
exports.age=18
module.exports.heiget=180 //将私有成员共享
---------------------------------
//b.js文件
const a=require("./a.js") //加载自定义的模块
console.log(a) //输出{name:"小王",age:18,height:180}
module 对象
在每个 .js 自定义模块中都有一个 module 对象,它里面存储了和当前模块有关的信息
module.exports 对象
在自定义模块中,可以使用 module.exports 对象,将模块内的成员共享出去,供外界使用。
外界用 require() 方法导入自定义模块时,得到的就是 module.exports 所指向的对象
注意:默认情况下,exports和module.exports指向同一个对象,但使用 require() 方法导入模块时,导入的结果,永远以 module.exports 指向的对象为准
通过exports只能通过.的方式向外暴露,而module.exports既可以用.也可以直接赋值
注意:为了防止混乱,建议不要在同一个模块中同时使用 exports 和 module.exports
--------------------------------------------------------------------------------------------------------------------------------
npm与包:
Node.js 中的第三方模块又叫做包。
如果想在项目中安装指定名称的包,需要运行如下的命令:
npm i 完整包的名称如果需要安装指定版本的包,可以在包 名之后,通过 @ 符号指定具体的版本
npm i 完整包的名称@2.22.2
包管理配置文件:
npm 规定,在项目根目录中,必须提供一个叫做 package.json 的包管理配置文件。用来记录与项目有关的一些配置信息
-------------------------------------------------------------------------------------------------------------------------
npm 包管理工具提供了一个快捷命令,可以在执行命令时所处的目录中,快速创建 package.json 这个包管理 配置文件:npm init -y
注意:
① 上述命令只能在英文的目录下成功运行!所以,项目文件夹的名称一定要使用英文命名,不要使用中文,不能出现空格。
② 运行 npm install 命令安装包的时候,npm 包管理工具会自动把包的名称和版本号,记录到 package.json 中。
-------------------------------------------------------------------------------------------------------------------------
dependencies 节点:package.json 文件中,有一个 dependencies 节点,专门用来记录使用 npm install 命令安装了哪些包。
-------------------------------------------------------------------------------------------------------------------------
一次性安装所有的包:可以运行 npm install 命令(或 npm i)一次性安装所有的依赖包
-------------------------------------------------------------------------------------------------------------------------
卸载包:可以运行 (npm uninstall 包名)命令,来卸载指定的包
注意:npm uninstall 命令执行成功后,会把卸载的包,自动从 package.json 的dependencies 中移除掉
-------------------------------------------------------------------------------------------------------------------------devDependencies 节点
如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议把这些包记录到 devDependencies 节点中。
与之对应的,如果某些包在开发和项目上线之后都需要用到,则建议把这些包记录到 dependencies 节点中。
用npm i 包名 -D(简写)或npm install 包名 --save-dev(完整版)把包记录到 devDependencies 节点中
解决下包速度慢的问题:
切换 npm 的下包镜像源,下包的镜像源,指的就是下包的服务器地址
npm config get registry 查看当前的下包镜像源
npm config set registry=https://registry.npm.taobao.org/ 将下包镜像源切换为淘宝镜像源
为了更方便的切换下包的镜像源,我们可以安装nrm这个小工具,利用nrm提供的终端命令,可以快速查看和切换下包的镜像源。
npm i nrm -g 通过npm包管理器,将nrm安装为全局可用的工具
nrm ls 查看所有可用的镜像源
nrm use taobao 将下包的镜像源切换为taobao镜像nrm test npm 测试npm镜像源的响应时间
npm search 包名 搜索包
npm version 查看所有模块版本
npm r 包名 删除包
npm -v 查看npm版本
npm i 下载当前项目所依赖的包
npm run build 打包文件
包的分类:
1. 项目包
那些被安装到项目的 node_modules 目录中的包,都是项目包。
项目包又分为两类,分别是:
开发依赖包(被记录到 devDependencies 节点中的包,只在开发期间会用到)
核心依赖包(被记录到 dependencies 节点中的包,在开发期间和项目上线之后都会用到
npm i 包名 -D 开发依赖包 会被记录到 devDependencies 节点下
npm i 包名 核心依赖包 会被记录到 dependencies 节点下
2.全局包
在执行 npm install 命令时,如果提供了 -g 参数,则会把包安装为全局包。
全局包会被安装到 C:\Users\用户目录\AppData\Roaming\npm\node_modules 目录下。
npm i 包名 -g 全局安装指定的包
npm uninstall 包名 -g 卸载全局安装的包
注意:
① 只有工具性质的包,才有全局安装的必要性。因为它们提供了好用的终端命令。
② 判断某个包是否需要全局安装后才能使用,可以参考官方提供的使用说明即可
yarn使用:
yarn相比于npm速度更快更安全
下载yarn: npm install -g yarn
开始新项目: yarn init
添加依赖包:yarn add 包名
查看yarn版本:yarn -v
添加指定版本包:yarn add 包名@xxx.xxx
添加全局依赖包:yarn global add 包名
如果某些包只在项目开发阶段会用到,在项目上线之后不会用到,则建议把这些包记录到 devDependencies 节点中。
记录到 devDependencies 节点中: yarn add 包名 -D
删除包: yarn remove 包名
安装项目的全部依赖:yarn install
打包文件: yarn build
切换 yarn的下包镜像源,下包的镜像源,指的就是下包的服务器地址
yrm工具可以快速查看和切换下包的镜像源。
yarn global add yrm 将yrm安装为全局可用的工具
yarn config get registry 查看当前的下包镜像源
yrm ls 查看所有可用的镜像源
yrm use taobao 将下包的镜像源切换为taobao镜像
yrm test npm 测试npm镜像源的响应时间
--------------------------------------------------------------------------------------------------------------------------------
模块的加载机制 :
优先从缓存中加载
模块在第一次加载后会被缓存。这也意味着多次调用 require() 不会导致模块的代码被执行多次。
注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。
1. 内置模块的加载机制:
内置模块是由 Node.js 官方提供的模块,内置模块的加载优先级最高。
例如,require('fs') 始终返回内置的 fs 模块,即使在 node_modules 目录下有名字相同的包也叫做 fs。
2. 自定义模块的加载机制:
使用 require() 加载自定义模块时,必须指定以 ./ 或 ../ 开头的路径标识符。在加载自定义模块时,如果没有指定 ./ 或 ../ 这样的路径标识符,则 node 会把它当作内置模块或第三方模块进行加载。
同时,在使用 require() 导入自定义模块时,如果省略了文件的扩展名,则 Node.js 会按顺序分别尝试加载以下的文件:
① 按照确切的文件名进行加载
② 补全 .js 扩展名进行加载
③ 补全 .json 扩展名进行加载
④ 补全 .node 扩展名进行加载
⑤ 加载失败,终端报错
3. 第三方模块的加载机制:
如果传递给 require() 的模块标识符不是一个内置模块,也没有以 ‘./’ 或 ‘../’ 开头,则 Node.js 会从当前模块的父 目录开始,尝试从 /node_modules 文件夹中加载第三方模块。
如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录。
例如,假设在 'C:\Users\itheima\project\foo.js' 文件里调用了 require('tools'),则 Node.js 会按以下顺序查找:
① C:\Users\itheima\project\node_modules\tools
② C:\Users\itheima\node_modules\tools
③ C:\Users\node_modules\tools
④ C:\node_modules\tools
4. 目录作为模块:
当把目录作为模块标识符,传递给 require() 进行加载的时候,有三种加载方式:
① 在被加载的目录下查找一个叫做 package.json 的文件,并寻找 main 属性,作为 require() 加载的入口
② 如果目录里没有 package.json 文件,或者 main 入口不存在或无法解析,则 Node.js 将会试图加载目录下的 index.js 文件。
③ 如果以上两步都失败了,则 Node.js 会在终端打印错误消息,报告模块的缺失:Error: Cannot find module 'xxx'
--------------------------------------------------------------------------------------------------------------------------------
Express:
通俗的理解:Express 的作用和 Node.js 内置的 http 模块类似,是专门用来创建 Web 服务器的。 Express 的本质:就是一个 npm 上的第三方包,提供了快速创建 Web 服务器的便捷方法。
express的基本使用:
路由的概念:在 Express 中,路由指的是客户端的请求与服务器处理函数之间的映射关系。
const express=require("express")//导入express
const app=express()//创建web服务器
//挂载路由
app.get("/user/:id",(req,res)=>{ //监听GET请求
//req:请求对象(包含了与请求相关的属性与方法)
//通过req.query对象可以访问的客户端通过查询字符串的形式发送到服务器的参数
//通过req.params可以获得动态匹配到的url中通过:匹配到的动态对象,默认是一个空对象
//res:响应对象(包含了图响应相关的属性与方法)
//通过res.send()方法,可以拔出力好的内容发送给客户端
console.log(req.params)
console.log(req.query)
res.send("哈哈")
})
//挂载路由
app.post("/user",(req,res)=>{ //监听post请求
res.send("bb")
})
app.listen(80,()=>{ //启动web服务器
console.log("http://127.0.0.1")
})
模块化路由:
为了方便对路由进行模块化的管理,Express 不建议将路由直接挂载到 app 上,而是推荐将路由抽离为单独的模块
//创建路由模块 a.js
const express=require("express")//导入express
const router=express.Router()//创建路由对象
router.get("/",(req,res)=>{ //挂载具体路由
res.send("get")
})
router.post("/",(req,res)=>{
res.send("post")
})
module.exports=router//向外到处路由对象
--------------------------------------------------
//注册路由模块 b.js
const express=require("express")//导入express
const app=express()//创建web服务器
const router=require("./a.js")//导入路由模块
app.use(router)//注册路由模块
//app.use()函数作用就是注册全局中间件
app.listen(80,()=>{ //启动web服务器
console.log("http://127.0.0.1")
})
----------------------------------------------------
//为路由模块添加前缀
app.use("/api",router)
中间件:
中间件,特指业务流程的中间处理环节
//全局中间件
const express=require("express")//导入express
const app=express()//创建web服务器
//通过调用 app.use(中间件函数),即可定义一个全局生效的中间件
app.use((req,res,next)=>{ //客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件
console.log(1)
var state=Date.now()
req.state=state //多个中间件之间,共享同一份req和res,可以统一为req或res对象添加自定义的属性或方法,供下游的中间件或路由进行使用
next() //在当前中间件业务处理完毕后,必须调用next()函数,表示吧流转关系转交给下一个中间件或路由
})
app.get("/",(req,res)=>{
console.log("get")
console.log(req.stale) //发起get请求时分别输出1,get和时间戳
})
app.listen(80,()=>{ //启动web服务器
console.log("http://127.0.0.1")
})
//可以使用 app.use() 连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行 调用,
-----------------------------------------------------------------------------------------
//局部中间件
const express=require("express")//导入express
const app=express()//创建web服务器
var a=(req,res,next)=>{//定义中间件函数a
console.log(1)
next()
}
var b=(req,res,next)=>{//定义中间件函数b
console.log(2)
next()
}
app.get("/",a,b,(req,res)=>{
console.log("get") //a,b这两个中间件只在当前路由中生效
})
app.post("/",(req,res)=>{
console.log("post") //a,b中间件不会影响这个路由
})
app.listen(80,()=>{ //启动web服务器
console.log("http://127.0.0.1")
})
中间件的5个使用注意事项 :
① 一定要在路由之前注册中间件
② 客户端发送过来的请求,可以连续调用多个中间件进行处理
③ 执行完中间件的业务代码之后,不要忘记调用 next() 函数
④ 为了防止代码逻辑混乱,调用 next() 函数后不要再写额外的代码
⑤ 连续调用多个中间件时,多个中间件之间,共享 req 和 res 对象
中间件分类:
① 应用级别的中间件
② 路由级别的中间件
③ 错误级别的中间件
④ Express 内置的中间件
⑤ 第三方的中间件
托管静态资源:
express 提供了一个非常好用的函数,叫做 express.static("文件夹路径"),通过它,我们可以非常方便地创建一个静态资源服务器
const express=require("express")//导入express
const app=express()//创建web服务器
app.use(express.static("./public")) //调用express()方法,快速的对外提供静态资源
app.listen(80,()=>{ //启动web服务器
console.log("http://127.0.0.1")
})
//这样就可以访问public目录中的所有文件了
//Express 在指定的静态目录中查找文件,并对外提供资源的访问路径。因此,存放静态文件的目录名不会出现在URL中。
托管多个静态资源目录:
如果要托管多个静态资源目录,请多次调用 express.static() 函数
注意:访问静态资源文件时,express.static() 函数会根据目录的添加顺序查找所需的文件
挂载路径前缀:
//如果希望在托管的静态资源访问路径之前,挂载路径前缀,则可以使用如下的方式:
app.use("./public",express.static("./public"))
--------------------------------------------------------------------------------------------------------------------------------
nodemon:
这个工具,它能够监听项目文件 的变动,当代码被修改后,nodemon 会自动帮我们重启项目,极大方便了开发和调试
安装 nodemon:
npm i -g nodemon
使用:
将node xxx.xxx改为npx nodemon xxx.xxx