Node
Node.js 是一个基于 Chromo V8 引擎的 JaveScript 运行环境.
Node.js 中无法调用 DOM,BOM等浏览器的内置API.
cd 路径 终端中的快捷键 ↑ 可以看快速定位到上一次执行的命令 tab 键,快速补全路径 esc 键, 快速清空当前已输入的命令 cls 命令, 清空终端
fs 文件系统模块
const fs = require('fs'); //导入fs模块 fs.readFile(path[, options], callback) //读取指定文件中的内容
- path :读取文件的存放路径
- options : 读取文件时采用的编码格式, 一般默认指定 utf8
- callback : 回调函数, 拿到读取失败和成功的结果 err dataStr
判断文件是否读取成功
Eg:
fs.readFile('./files/1.txt', 'utf8', function(err, dataStr) { if(err) { //如果读取文件失败,则err的值为错误对象,dataStr的值为 undefined return console.log('读取文件失败!' + err.message); } else { //如果读取文件成功 则err的值为null console.log('读取文件成功!' + dataStr); } })
fs.writeFile(file, data[, options], callback) //向指定文件写入内容
- file : 表示文件存放的路径
- data : 表示写入的内容
判断文件是否写入成功
fs.writeFile('f:/files/2.txt', 'abck', function(err) { if(err) { return console.log('文件写入失败!' + err.message) } console.log('文件写入成功') //文件写入成功 err 的值为 null }) //fs.writeFile() 方法只能用来创建文件,不能用来创建路径 //重复调用 fs.writeFile() 写入同一个文件,新写的内容会覆盖之前的旧内容
路径动态拼接问题
在使用 fs 模块操作文件时, 如果提供的操作路径是以./ 或 …/ 开头的相对路径, 很容易出现路径动态拼接错误的问题.
原因: 代码在运行的时候, 会以 执行 node 命令所处的目录, 动态拼接出被操作文件的完整路径.
解决办法: 提供的操作路径换成 绝对路径 \\ ; 移植性很差 , 不利于维护
__dirname //表示当前文件所处的目录(双下划线) __dirname + 'url'
path 路径模块
路径拼接
path.join(); // 可以把多个路径片段拼接为完整的路径字符串 eg: const pathStr = path.join('/a', '/b/c', '../', './d', 'e') //(../会抵消一成路径) console.log(pathSrt) // 输出 \a\b\d\e const pathStr2 = path.join(__dirname,''); //路径的拼接
path.basename() //获取路径中的文件名 eg: const fpath = '/a/b/c/index.html' const fullName = path.basename(fpath) //得到 index.html const nameWithoutExt = path.basename(fpath,'html') //获得没有扩展名的文件名称
path.extname(path) //获取路径中的扩展名部分;参数,返回值均为字符串形式 const fpath = '/a/b/c/index.html' const fext = path.extname(fpath) //输出 .html
http模块
const http = require('http') //导入http模块 //127.0.0.1 或者 localhost 代表我们自己的这台电脑 //端口号 每个端口号不能同时被多个端口号占用,URL中的80端口可以被省略
创建最基本的web 服务器
// 1. 导入http模块 const http = require('http') // 2. 创建Web服务器 const server = http.creatServer() // 3. 为服务器绑定 request 事件 //server.on(事件名称,回调函数) server.on('request', (req, res) => { //只要有客户端来请求我们自己的服务器, 就会触发 request 事件, 从而调用这个事件处理函数 //req是请求对象,包含了与客户端相关的数据和属性 //req.url是客户端请求的 URL 地址 || req.method是客户端请求的 method 类型 //=============================================== //res响应对象 //res.end() 向客户端发送指定的内容, 并结束这次请求的处理过程 //======================解决中文乱码的问题=================== const str = '您请求的 URL 地址是 $(req.url), 请求的 method 类型为 $(req.method)' res.setHeader('Content-Type', 'text/html; charset=utf-8') //header()函数的作用是:发送一个原始 HTTP 标头[Http Header]到客户端. //标头 (header) 是服务器以 HTTP 协义传 HTML 资料到浏览器前所送出的字串,在标头与 HTML 文件之间尚需空一行分隔。在 PHP 中送回 HTML 资料前,需先传完所有的标头。 res.end(str) }) // 4. 启动服务器 //server.listen(端口号, cb回调) server.listen(80, () => { //函数体 })
ctrl + c 重启
解决中文乱码的问题
根据不同的 url 响应不同的 html 内容
const http = require('http') const server = http.creatServer() server.on('request', (req.res) =>{ const url = req.url //获取请求的url地址 let content = '<h1>404 Not found!</h1>' //设置默认的响应内容 if(url === '/' || url === '/index.html') { content = '<h1>首页</h1>' } else if(url === '/about.html') { content = '<h1>关于页面</h1>' } res.setHeader('Content-Type', 'text/html; charset=utf-8') res.end(content) }) server.listen(80,() => { })
模块化
模块作用域
用户自定义模块
向外共享模块作用域的成员
module对象储存了和当前模块有关的信息
moduel.exports
对象
在自定义模块中使用 module.exports 对象,将模块内的成员共享出去
外界用require() 方法导入自定义模块时, 得到的就是 module.exports 指向的对象
module.exports.username = 'zs' //向 module.exports 对象挂截 username 属性 module.exports.sayHello = function() { console.log('Hello') } // 向 module.exports 对象挂截 sayHello 方法
注意点:
- 导入的结果永远以 module.exports 指向的对象为准
- module.exports === exports
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R9yewj0h-1646530819789)(C:\Users\Lenovo\Desktop\typora\img\module.export.jpg)]
CommonJS规范
- 每个模块内部, module 变量代表当前模块
- module 变量是一个对象, 他的exports 属性时对外的接口
- 加载某个模块时, 其实时加载模块的 module.exports 属性
npm与包
- 包是由第三方个人或团队开发出来的,免费供所有人使用
- Node.js 的内置模块仅提供了一些底层的API,导致在基于内置模块进行项目开发时,效率很低,包是基于内置模块封装出来的,提供了更高级,更方便的 API ,极大的提高了开发效率
包共享平台 https://www.npmjs.com/ 搜包https://registry.npmjs.org/ 下包
npm初体验
格式化时间的高级做法
在项目中安装包的命令
npm install moment
npm i moment
若要一次安装多个包 多个包名称中间用空格隔开
// 导入 moment 包 注意:导入的包就是装包时候的包 const moment = require('moment') const dt = moment().format('YYYY-MM-DD HH:mm:ss')
初次装包后多的两个文件
node_modules 文件夹 用来存放所有已安装到项目中的包. require() 导入的第三方包,就是从这个目录中查找并加载包
package-lock.json 配置文件用来记录 node_modules 目录下的每一个包的下载信息,例如包的名字,版本号,下载地址等.
如何安装指定版本的包
如 需要安装 2.22.2版本的moment 包
npm i moment@2.22.2
包的语义化版本规范
包的版本号是以 “点分十进制” 形式进行定义的, 总共有三位数字 例如2.24.0
三位数字代表的含义如下
- 大版本
- 功能版本
- Bug 修复版本
版本号规则的提升: 只要前面的版本号增长了, 则后面的版本号归零
包管理配置文件
什么是包管理配置文件
npm 规定, 在项目根目录, 必须提供一个叫做 package.json 的包管理配置文件.用来记录与项目有关的一些配置信息.例如:
- 项目的名称,版本号,描述
- 项目中都用到了那些包
- 那些包只会在开发期间用到
- 那些包在开发和部署时都需要用到
多人协作的问题
问题: 第三方包的体积过大,不方便团队成员之间共享项目源代码
解决方案: 共享时剔除 node_modules(只上传源代码,包自己联网下载)
这个时候就要从package.json 这个配置文件中查看都安装了那些包
注意: 一定要把 node_modules 文件夹 , 添加到 .gitignore 忽略文件中
快速创建 package.json
可以在 执行命令时所处的目录中, 快速创建 package.json 这个包管理配置文件
npm init -y
- 新建文件夹后,不要写任何代码,先执行快捷创建 package.json 文件
- 上述命令只能在英文的目录下成功运行! 所以,项目文件夹的名称一定要使用英文命名,不要使用中文,不能出现空格.
- 运行 npm install 命令安装包的时候 , npm 包管理工具会自动把包的名称和包的版本号,记录到 package.json 中
dependencies 节点
package.json 文件中, 有一个 dependencise 节点, 专门用来记录您使用 npm install 命令安装了那些包
一次性安装所有的包
npm install
或者npm i
执行 npm install 命令时, npm 包管理工具会先读取 package.json 中的 dependencies 节点,读取到记录的所有依赖包名称和版本号之后, npm 包管理工具会把这些包一次性下载到项目中
卸载包
npm uninstall 包名称
命令执行成功之后,会把卸载的包,自动从 package.json 和 dependencies 中移除
devDependencies 节点
如果某些包只在项目开发阶段用到, 在项目上线后不会用到, 建议把这些包 记录到 devDependencies 节点中,
如果某些包在开发和项目阶段都需要用到, 则建议把这些包记录到 dependencies 节点中
npm i 包名 -D
安装指定的包,将包记录到 deDependencies 节点中
解决下包速度慢的问题
查看当前下包的镜像源(下包的服务器地址)
npm config get registry
将下包的镜像源切换为淘宝镜像源
npm config set registry=https://registry.npm.taobao.org/
nrm 小工具
- 将 nrm 安装为全局可用的工具
npm i nrm -g
- 查看所有可用的镜像源(*代表当前正在使用的服务器)
nrm ls
- 将下包的镜像源切换为 taobao 镜像
nrm use taobao
包的分类
项目包
- 开发依赖包( devDependencies ,只会在开发期间用到)
- 核心依赖包(dependencies , 开发期间,和项目上线之后都会用到)
全局包
被安装到了 C:\Users\用户目录\AppData\Roaming\npm\node_modules 目录下
npm i 包名 -g
全局安装指定包
npm uninstall 包名 -g
卸载全局安装的包
包的内部结构
- 包必须以单独的目录而存在
- 包的顶级目录下要必须包含 package.json 这个包管理配置文件
- package.json 中必须包含 name, version, main 这三个属性, 分别代表 包的名字 , 版本号, 包的入口
开发属于自己的包
转义 HTML 中的特殊字节
function htmlEscape(htmlstr) { return htmlstr.replace(/<|>|"|&/g, (match) => { switch(match) { case '<': return '<' case '>': return '>' case '"': return '"' case '&': return '&' } }) }
还原 HTML 中的特殊字符 htmlUnEscape()
function htmlUnEscape(str) { return str.replace(/<|>|"|&/g, (match) => { switch(match) { case '<': return '<' case '>': return '>' case '"': return '"' case '&': return '&' } }) }
- 新建 文件夹,作为包的根目录
- 在该文件夹新建如下三个文件:
- package.json 包配置管理文件
{ "name": "包名", "version": "版本号", "main": "包的入口", "description": "包的简短的描述信息", "keywords": 关键字[,,] "license": "开源许可协议" }
- index.js 包的入口文件
- README.md 包的说明文档
功能模块化拆分
编写包的说明文档
安装方式, 导入方式, 实现功能, 开源协议
模块的加载机制
有限从缓存中加载
模块在第一次被加载后会被缓存, 所以多次调用 require() 不会导致模块的代码被执行多次.
内置模块的加载优先级最高
自定义模块的加载
- 使用 require() 加载自定义模块时, 必须指定以 ./ 或 …/ 开头的路径标识符.如果没有指定 ./ 或 …/ 这样的路径标识符,则 node 会把它当作 内置模块 或 第三方模块 进行加载.
- require() 省略文件扩展名,Node.js会按以下顺序加载文件(直到加载成功停止):
- 按确切的文件名进行加载
- 补全 .js 扩展名 进行加载
- 补全 .json 扩展名进行加载
- 补全 .node 扩展名进行加载
- 加载失败, 终端报错
第三方模块的加载机制
如果传递给 require( ) 的模块标识符不是一个内置模块, 也没有以 ‘./’ 或 ‘…/’ 开头,则 Node.js 会从当前模块的父目录开始尝试加载文件,若还没找到,再移动到上一层父目录中进行加载,直到文件系统的根目录.