文章目录
- node学习笔记01
- 前置知识
- 为什么JavaScript可以在浏览器中被执行?
- 为什么JavaScript可以操作DOM和BOM
- 浏览器中的JavaScript运行环境
- Nodejs概述
- Nodejs中的JavaScript运行环境
- 基本命令
- fs文件系统模块
- fs.readFile() 读取指定文件中的内容
- fs.writeFile() 向指定的文件中写入内容
- 练习-考试成绩整理
- path路径模块
- path.join() 路径拼接
- path.basename() 获取路径中的文件名
- path.extname() 获取路径中的文件扩展名
- http模块
- 创建最基本的web服务器
- 根据不同的url响应不同的html内容
- 向浏览器响应html、css、js资源文件
- 模块化
- 什么是模块化
- 加载模块 require
- 模块的加载机制
- 向外暴露成员 module对象
- module.exports 指向暴露的对象
- exports 指向暴露的对象
- CommonJs规范 总结
- npm与包
- 包分类
- 包管理配置文件 package.json
- npm镜像服务器
- npm的包结构规范
- 自定义包
- 初始化包结构
- 1.格式化日期
- 2.转义HTML中的特殊字符
- 3.还原HTML中的特殊字符
node学习笔记01
前置知识
为什么JavaScript可以在浏览器中被执行?
浏览器中有JavaScript解析引擎,可以将待执行的JS代码解析执行。
不同的浏览器使用不同的JavaScript解析引擎: Chrome浏览器 => V8解析引擎
为什么JavaScript可以操作DOM和BOM
JS通过调用浏览器提供的内置Web API来操作DOM和BOM
浏览器中的JavaScript运行环境
运行环境:代码正常运行需要的环境
1.V8引擎负责解析和执行JavaScript代码
2.内置API是由运行环境提供的特殊接口,只能在所属的运行环境中被调用
Nodejs概述
Nodejs是基于Chrome V8 引擎的JavaScript运行环境
- 浏览器是JavaScript的前端运行环境
- Nodejs是JavaScript的后端运行环境,可以让JavaScript进行后端开发
Nodejs中的JavaScript运行环境
基于V8引擎,但是不是浏览器运行环境,所以Nodejs中无法调用DOM和BOM等浏览器内置API
基本命令
执行node: node js文件路径
fs文件系统模块
fs模块是Node.js内置的操作文件的模块。
模块使用步骤
1.引入模块
2.使用模块
const fs = require('fs')
内置变量与方法
-
__dirname
: 当前文件所处的目录 -
fs.readFile()
: 读取指定文件中的内容 -
fs.writeFile()
: 向指定的文件中写入内容
fs.readFile() 读取指定文件中的内容
语法: fs.readFile(path[,options],callback)
- path:表示文件的路径
- options:设置读取文件的编码格式,默认指定uft8
- callback:文件读取完成后,通过回调函数拿到读取的结果
- 参数1: 读取失败之后,用于接收失败的信息
- 参数2: 读取成功之后,接收读取的数据
const fs = require('fs');
fs.readFile('./1.txt','utf8',function(err,dataStr){
/*
dataStr成功的结果,err失败的结果
读取成功err用null
*/
})
fs.writeFile() 向指定的文件中写入内容
语法: fs.writeFile(file,data[,options],callback)
- file 文件的路径
- data 写入的内容
- options 指定写入文件内容的格式,默认值是utf8
- callback 写入完成后的回调函数
- 参数 写入失败之后,用于接收失败的信息
const fs = require('fs');
fs.readFile('./1.txt','abc',function(err){
//文件写入成功err是null
})
使用说明
1.fs.writeFile()方法只能用来创建文件,不能用来创建路径
2.重复调用fs.writeFile()写入同一个文件,新的内容会覆盖新的内容
练习-考试成绩整理
需求
思路1
1.使用fs.readFile读取成绩.txt文件
2.获取到内容之后,根据空格进行分割数组,循环替换
3.合并数组通过换行\r\n
连接数组中的每个元素
const fs = require('fs')
fs.readFile('./files/成绩.txt', 'utf8', function(err, dataStr) {
if (err) return console.log('读取文件失败!' + err.message)
const arrOld = dataStr.split(' ')
// 循环分割后的数组,对每一项数据,进行字符串的替换操作
const arrNew = []
arrOld.forEach(item => {
arrNew.push(item.replace('=', ':'))
})
//把新数组中的每一项,进行合并,得到一个新的字符串
const newStr = arrNew.join('\r\n')
// 调用 fs.writeFile() 方法,把处理完毕的成绩,写入到新文件中
fs.writeFile('./files/成绩-ok.txt', newStr, function(err) {
if (err) {
return console.log('写入文件失败!' + err.message)
}
console.log('成绩写入成功!')
})
})
path路径模块
path模块是Node.js内置的处理路径的模块
-
path.join()
: 将多个路径片段拼接成一个完整的路径字符串 -
path.basename()
: 从路径字符串中,将文件名解析出来
const path = require('path');
path.join() 路径拼接
语法:path.join([…paths])
返回值:拼接好的路径字符串
路径中出现../
在当前拼接好的路径上回退一层。
../
表示上一层目录./
表示当前目录
const pathStr = path.join('/a','/b','../') // \a
path.basename() 获取路径中的文件名
作用:获取路径中的最后一部分,通常通过这个方法获取路径中的文件名
语法: path.basename(path[,ext])
- path:表示一个路径的子字符串
- ext: 表示文件扩展名
- 没写会显示文件扩展名
- 写了之后会省略文件扩展名
- 返回值: 路径中的最后一部分
const path = require('path')
const fpath = '/a/b/c/index.html'
const fullName = path.basename(fpath)
console.log(fullName)//index.html
const nameWithoutExt = path.basename(fpath, '.html')
console.log(nameWithoutExt) //index
path.extname() 获取路径中的文件扩展名
语法: path.extname(path)
const fpath = '/a/b/c/index.html'
const fext = path.extname(fpath)
console.log(fext) //.html
http模块
http模块是Node内置创建Web服务器的模块,将普通的电脑变成Web服务器
const http = require('http')
IP地址是互联网上每台计算机的唯一地址
端口号:表示一台电脑中的每个Web服务,在实际应用中url中的80端口可以省略
创建最基本的web服务器
1.导入http模块
2.创建web服务器实例 server = http.createServer
3.为服务器实例server .on
绑定request事件,监听客服端的请求,客户端请求服务器会触发request请求
4.启动服务器server.listen(端口号,回调函数)
const http = require('http')
const server = http.createServer()
server.on('request', (req, res) => {
//客户端请求服务器会触发request请求
})
server.listen(8080, () => {
//服务器启动成功的回调函数
})
只要服务器接收到了客户端的请求,就会触发request事件,调用request事件处理函数。
request事件处理函数的参数
- 第一个参数req请求对象:存储客户端相关的数据或属性
- req.url : 客户端请求的URL地址
- req.method: 客户端请求的method类型
- 第二个参数res响应对象:存储服务器相关的数据或属性
- res.end(响应的内容):向客户端响应指定内容,并结束本次请求。
问题1:当res.end()发送中文内容时,会出现乱码
解决办法: 设置响应头 Content-Type
的值为text\html;charset = uft-8
server.on('request', (req, res) => {
const str = `您请求的 URL 地址是 ${req.url},请求的 method 类型为 ${req.method}`
// 调用 res.setHeader() 方法,设置 Content-Type 响应头,解决中文乱码的问题
res.setHeader('Content-Type', 'text/html; charset=utf-8')
res.end(str)
})
根据不同的url响应不同的html内容
1.获取请求的url地址
2.设置默认的响应内容为404 Not found
3.不同url的处理
4.设置Content_Type 响应头,防止中文乱码
5.使用res,end()
把内容响应给客户端
server.on('request', (req, res) => {
const url = req.url
// 设置默认的响应内容为 404 Not found
let content = '<h1>404 Not found!</h1>'
// 判断用户请求的是否为 / 或 /index.html 首页
// 判断用户请求的是否为 /about.html 关于页面
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)
})
向浏览器响应html、css、js资源文件
响应文件的流程 – 实际给客户端的还是字符串
请求index.html
之后,发现html里面有依赖./index.css
和./index.js
,会根据html所在的目录拼接文件名再去服务器请求资源
模块化
什么是模块化
模块:把一个大文件拆成独立并相互依赖的多个小模块
**模块作用域:**在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问\
模块化的好处
- 提高了代码的复用性
- 提高了代码的可维护性
- 可以实现按需加载
nodejs中模块的分类
- 内置模块,由Nodejs官方提供,如fs、path等
- 自定义模块,用户创建的每一个js文件都是自定义模块
- 第三方模块,由第三方开发出来的模块,使用前需要先下载
加载模块 require
使用require()方法加载其他模块时,会执行被加载模块中的代码
- 内置模块 | 第三方模块
require('模块名')
- 自定义模块
require(’请求路径‘)
js后缀名可以省略,默认是以.js结尾,必须指定以./
或../
开头的路径标识符
模块的加载机制
使用require()方法加载其他模块时,会执行被加载模块中的代码
- 优先从缓存加载:模块在第一次加载后会被缓存,多次调用require()不会导致模块的代码被执行多次
- 内置模块的加载优先级最高
- require()加载自定义模块时,必须指定以
./
或../
开头的路径标识符 - require()导入自定义模块,如果省略了文件的扩展名,Node会按顺序尝试加载 ①确切的文件名进行加载 ②补全
.js
扩展名进行加载 ③补全.json
扩展名进行加载 ④ 补全.node
扩展名进行加载 ⑤加载失败
当目录作为模块标识符,传递给require()进行加载时
1.先去目录下找package.json
文件,并寻找main属性,属性值作为加载的入口
2.如果没有package.json
文件或者main入口不存在或无法解析,尝试加载目录下的index.js
3.报错
向外暴露成员 module对象
在每个.js自定义模块中都有一个module对象,该对象存储了和当前模块有关的信息
Module {
id: '.',
path: '', //当前文件的存储目录
exports: {}, //向外暴露成员
filename: '', //当前文件的路径 目录+文件名
//.....
}
module.exports 指向暴露的对象
在自定义模块中,module.exports
对象,将模块内的成员暴露出去。
外界使用
require()
方法导入自定义模块时,得到的就是module.exports
指向的对象
const age = 20
// 向 module.exports 对象上挂载 username 属性
module.exports.username = 'ranan'
// 向 module.exports 对象上挂载 sayHello 方法
module.exports.sayHello = function() {
console.log('Hello!')
}
module.exports.age = age
// 让 module.exports 指向一个全新的对象 那么require引入是新对象
module.exports = {
nickname: 'biubiu',
sayHi() {
console.log('Hi!')
}
}
exports 指向暴露的对象
因为module.exports
写起来复杂,所以提供另外一个对象exports对象
默认情况下,exports和module.exports指向同一个对象 exports==module.exports
如果人为修改了指向,最终会以module.exports为准。
CommonJs规范 总结
1.每个模块内部都有module对象,该对象代表当前模块
2.module变量的exports属性是对外的接口
3.require()方法加载是module.exports指向的对象
npm与包
Nodejs中第三方模块又叫做包,包基于内置模块封装出来的,提供了更高级、方便的API,极大的提高了开发效率。
npm是包管理工具。
初次装包完成后,在项目文件夹下增加了node_modules
的文件夹和package-lock.json
的配置文件
- node_modules:存放所有已安装到项目的包,
require()
导入第三方包时,就是从这个目录中查找并加载包的 - package-lock.json:记录node_modules目录下每一个包的名字、版本号、地址等下载信息
说明
-
npm i xxx@版本号
@版本号可以省略,省略默认安装最新版本。 - 多次安装同一个包,后面的会覆盖前面的
- 包的版本号: 大版本: 功能版本: Bug修复版本 前面版本号增长了,后面的版本号就归零
包分类
- 项目包:安装到项目node_modules目录中的包
- 开发依赖包:devDependencies节点中的包, 只在开发阶段会用到,项目上线后不会使用
- 核心依赖包:dependencies 开发和上线都使用,默认会下载到dependencies节点
- 全局包:在执行
npm install
命令时,使用-g参数,会把包安装为全局包
项目包的安装与卸载
npm install #一次性安装dependencies下的所有包
npm install 包名 # 安装包到dependencies下
npm install 包名 --save-dev # 安装包到devDependencies下
npm install 包名 -D # 简写形式
npm uninstall 包名 # 会自动从package.json的dependencies中移除包信息
全局包的安装与卸载
npm i 包名 -g # 全局安装指定的包
npm uninstall 包名 -g # 卸载全局安装的包
包管理配置文件 package.json
npm规定,在项目根目录下,必须提供package.json
的包管理配置文件,用于记录项目的配置信息如项目名称、版本号、使用的包等。
创建package.json的快捷命令: npm init -y
该快捷命令只能在英文的目录下成功运行,目录不能有空格
npm镜像服务器
切换npm的下包镜像源 - 解决下包速度慢的问题
# 查看当前的下包镜像源
npm config get registry
# 切换
npm config set registry=https://registry.npmmirror.com
npm的包结构规范
1.包必须以独立目录存在
2.包的顶级目录下必须包含package.json
这个包管理配置文件
3.package.json
中必须包含name包名、version包版本号、main包的入口这三个属性
自定义包
登录之后
进入到包的根目录,npm publish
发布包
运行npm unpublish 包名 --force
从npm删除已发布的包
1.只能删除72小时以内发布的包。
2.使用命令删除的包,在24小时内不允许重复发布。
初始化包结构
1.新建my-tools文件夹,作为包的根目录
2.新建package.json包管理配置文件、index.js包的入口文件、README.md包说明文件
初始化package.json
{
"name": "my-tools", //包名不能重复
"version": "1.0.0",//包版本号
"main": "index.js",//包入口
"description": "提供了格式化时间、HTMLEscape相关的功能",//包的描述信息
"keywords": [//搜索关键字
"my",
"dateFormat",
"escape"
],
"license": "ISC" //开源许可协议
}
main属性的作用
如果导入的是一个目录,会先搜索这个目录是否有package.json文件,如果有则看有没有main属性,默认会导入main属性值的文件
1.格式化日期
将传入的时间进行格式化
分别获取年月日时分秒,进行格式拼接,不足10的补0
// 定义格式化时间的函数
function dateFormat(dateStr) {
const dt = new Date(dateStr)
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 `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
// 定义一个补零的函数
function padZero(n) {
return n > 9 ? n : '0' + n
}
module.exports = {
dateFormat
}
2.转义HTML中的特殊字符
将< > " &
HTML的特殊字符转义成实体字符,防止用户提交表单时填写HTML字符串
// 定义转义 HTML 字符的函数
function htmlEscape(htmlstr) {
return htmlstr.replace(/<|>|"|&/g, match => {
switch (match) {
case '<':
return '<'
case '>':
return '>'
case '"':
return '"'
case '&':
return '&'
}
})
}
3.还原HTML中的特殊字符
转义HTML中的特殊字符的逆操作
// 定义还原 HTML 字符串的函数
function htmlUnEscape(str) {
return str.replace(/<|>|"|&/g, match => {
switch (match) {
case '<':
return '<'
case '>':
return '>'
case '"':
return '"'
case '&':
return '&'
}
})
}