node入门
1、JS运行环境:
前端浏览器环境:V8引擎解析执行、浏览器所提供的API调用
Node.js后端环境(基于V8引擎的JS运行环境):V8引擎、API(他不是浏览器环境,所以无法调用web的dom和bom)
2、 JS学习:JS语法+DOM+BOM+第三方库(jq等)
Node学习:JS语法+Node模块(fs、path、http等)+第三方库(express等)
3、fs文件系统模块:
- fs.readFile() 方法,用来读取指定文件中的内容
fs.readFile(path路径, option可选编码参数, callback回调函数,包含data和err)
- fs.writeFile() 方法,用来向指定的文件中写入内容
fs.writeFile(path路径, data内容, option可选编码参数, callback回调函数,包含data和err)
IO操作为宏任务,若同时存在write和read并操作同一文件,先执行write:
const fs = require("fs") //IO读取是宏任务,在main、micro打印之后 fs.readFile("./1.txt","utf8",function(err, dataStr){ if (err) { return console.log(err); } console.log(dataStr); }) new Promise((resolve, reject)=>{ resolve() }).then(()=>{ console.log("micro"); }) console.log("main"); fs.writeFile("./1.txt","helloNode1",function(err, dataStr){ if (err) { return console.log(err); } console.log(dataStr); }) //main //micro //undefined //helloNode1
- 路径动态拼接(相对路径问题)
路径错误指的是在执行js的时候用node .\目录\js文件运行时,js文件内的路径调用处于不同层路径,导致调用失败。
使用绝对路径,但是移植性差,不利于后期维护
使用__dirname解决,表示当前文件所处的目录
fs.readFile(__dirname+"/1.txt","utf-8",(err, dataStr)=>{ if (err) { return console.log(err.message); } console.log(dataStr); })
4、path路径模块
-
path.join() 方法,用来将多个路径片段拼接成一个完整的路径字符串
path.join([...path路径片段]) 返回拼接好的字符串,相比于+号,他会自动处理一些不必要的错误,比如./和/
- path.basename() 方法,用来从路径字符串中,将文件名解析出来
path.basename(path路径, option可选后缀,如果加上,返回的文件名就不带后缀)
- path.extname(),可以获取路径中的扩展名部分
path.extname(path路径),返回扩展名
5、http模块:创建web服务器
- http.createServer() 创建服务器实例
const http = require("http") //实例化服务器 const server = http.createServer() //服务器绑定request事件 server.on('request',(req, res)=>{ //若有客户端请求,则内容触发 console.log("服务器收到请求"); }) //启动服务器 server.listen(80,()=>{ console.log("服务器启动成功"); })
req(request):请求对象,访问与客户端相关的数据或属性,如req.url、req.method等
res(respond):响应对象,返回响应内容,并结束本次处理过程,如res.end()
//服务器绑定request事件 server.on("request", (req, res) => { //若有客户端请求,则内容触发 console.log(req.method, req.url); let content = "404"; //动态路由Î if (req.url === "/" || req.url === "/index.html") { content = "中国"; } //响应,如数据,html等 //防止中文乱码,要在响应头加上格式 res.setHeader("Content-Type", "text/html; charset=utf-8"); res.end(content); });
6、模块化
模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换的单元。
把代码进行模块化拆分的好处:
- 提高了代码的复用性
- 提高了代码的可维护性
- 可以实现按需加载
1、规范:比如如何引用;如何暴露
2、模块分类:
- 内置模块(内置模块是由 Node.js 官方提供的,例如 fs、path、http 等)
- 自定义模块(用户创建的每个 .js 文件,都是自定义模块)
- 第三方模块(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)
3、加载模块:require() 加载的时候会执行里面的代码,其可以省略.js后缀名
4、模块作用域:在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问。防止变量污染,命名冲突等
5、Module对象,里面存储了和当前模块有关的信息
暴露:module.exports { },将模块内的成员共享出去,供外界使用。其以module.export所导出的对象为准(为了简化,写exports也可以,他们初始指向同一个堆,但是要注意直接赋值的时候堆的转换,最终以module.exports为准,还要注意exports最为最后一个对象时,是无法输出的)
exports.age = 20 //此时module.exports和exports都为age=20
module.exports.name = "jacky" //此时module.exports和exports都指向age=20, name=jacky的堆 module.exports = { name: "JJ" //最终导出,此时module.exports指向另一个堆 }
exports = {
gender: male //exports是无法作为最终输出的,所以这行无效。除非下面加上module.exports = exports输出
}
6、node遵循了 CommonJS 模块化规范,CommonJS 规定了模块的特性和各模块之间如何相互依赖
- 每个模块内部,module 变量代表当前模块。
- module 变量是一个对象,它的 exports 属性(即 module.exports)是对外的接口。
- 加载某个模块,其实是加载该模块的 module.exports 属性。require() 方法用于加载模块。
7、npm(包管理)和包(第三方模块,其也是基于内置模块开发出来的)
npm:node_modules 文件夹用来存放所有已安装到项目中的包。
package-lock.json 配置文件用来记录 node_modules 目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等
1、 @ 符号安装指定具体的版本
2、版本号规范:例如 2.24.0
-
- 第1位数字:大版本
- 第2位数字:功能版本
- 第3位数字:Bug修复版本
- 版本号提升的规则:只要前面的版本号增长了,则后面的版本号归零。
3、package.json包管理配置文件
记录项目的名称、版本号、描述等,项目中都用到了哪些包,哪些包只在开发期间会用到,那些包在开发和部署时都需要用到
在上传项目时,由于node_modules文件夹过大,一般会在.gitignore中忽略上传,他人通过package.json去下载对应的包
其中必须包含 name,version,main 这三个属性,分别代表包的名字、版本号、包的入口
npm init -y直接生成该默认文件,如果不-y则需要配置文件如版本,名称等。路径不能中文。
- dependences节点:专门用来记录使用 npm install 命令安装了哪些包。上线时和开发时都会用到的包会记录在这,卸载时会去除。
- devDependencies 节点:某些包只在项目开发阶段会用到,在项目上线之后不会用到,则把这些包记录到 devDependencies 节点中,使用 -D(完整写法 --save-dev)命令
4、包分类
-
- 项目包:node_modules里的包。又分为项目(核心)依赖包(dependences)和开发依赖包(devDependencies)
- 全局包:-g。被安装到系统目录下。只有工具性质的包,才有全局安装的必要性。因为它们提供了好用的终端命令,比如webpack等。
5、开发自己的包:
package.json包管理(main/version/main/decription描述/keywords数组,提供搜索关键字)、index.js包入口、README.md说明文档
模块拆分:在 index.js 中,导入两个模块,得到需要向外共享的方法并使用 module.exports 把对应的方法共享出去(展开)
// 这是包的入口文件 const date = require('./src/dateFormat') const escape = require('./src/htmlEscape') // 向外暴露需要的成员 module.exports = { ...date, ...escape }
8、模块加载机制
1、模块优先从缓存中加载,提高加载效率,require只会执行一次
2、内置模块加载优先级最高,同名优先加载内置,一般也不会有和内置模块名相同的包
3、使用 require() 加载自定义模块时,必须指定以 ./ 或 ../ 开头的路径标识符,否则会认为是第三方或内置模块
4、如果省略文件后缀,会按顺序查找加载:
-
- 按照确切的文件名进行加载
- 补全 .js 扩展名进行加载
- 补全 .json 扩展名进行加载
- 补全 .node 扩展名进行加载
- 加载失败,终端报错
5、第三方模块加载机制:如果当前路径的node_module没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录
6、目录作为加载模块:先找package.json,然后找里面的main;如果没有,就找index.js
9、其他一些内置模块:
1、events:事件常用方法
const EventEmitter = require("events"); // 1.创建事件发射器 const emitter = new EventEmitter(); // 2.监听某一个事件 // addListener是on的alias简写 emitter.on('click', (args) => { console.log("监听1到click事件", args); }) const listener2 = (args) => { console.log("监听2到click事件", args); } emitter.on('click', listener2) // 3.发出一个事件以及取消该事件 setTimeout(() => { emitter.emit("click", "coderwhy", "james", "kobe"); emitter.off("click", listener2); emitter.emit("click", "coderwhy", "james", "kobe"); }, 2000);
2、until:工具
-
- util.format(格式化输出字符串);
- util.isArray(检查是否为数组);
- util.RegExp(是不是正则);
- util.isDate(是不是日期型);
- util.inherits(child, parent)实现继承;
3、qs:专门用来处理查询字符串
-
- qs.parse()将 URL 解析成对象的形式
- qs.stringify()将对象序列化成 URL 的形式