Node 第 1 天
- 总体node流程
- 使用node操作文件
- node开发基础服务器
- node框架:express
- 数据库mysql, sql语句
- http协议, cookie, session, token jwt
2.1 为什么 JavaScript 可以在浏览器中执行
- 浏览器中的JS
- ECMAScript + DOM + BOM
- JS解析引擎-V8引擎
- 因为浏览器提供了DOM和BOM的API,所以JS才能够使用DOM和BOM
- 浏览器是JS的一种运行环境
- Node.js运行环境
- Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境
2.2 JavaScript 可以操作 DOM
和 BOM
- 每个浏览器都内置了
DOM
、BOM
这样的API
函数,因此,浏览器中的JavaScript
才可以调用它们。
3. 初识 Node
3.1 什么是 Node
能够了解 Node 是一个运行环境,并不是一门后台语言
Node.js
是一个基于 Chrome V8
引擎的 JavaScript
运行环境
*Node 实际上就是一个 JavaScript
运行环境,它集成了 v8
引擎, 从而能对 JavaScript
代码进行解析
3.2 Node
中的 JavaScript
环境
- Node 运行环境包含两个部分,分别是:
V8
引擎,主要负责解析JavaScript
代码- 内置
API
,我们学习Node.js
重点就是学习这些内置的API
,从而能够完成后台的开发
Node
运行环境和 浏览器运行环境的区别
-
浏览器是
JavaScript
的前端运行环境 -
Node.js
是JavaScript
的后端运行环境 -
Node
环境中 没有DOM
和BOM
的API
,即在Node
中无法调用DOM
和BOM
等浏览器内置API
同理,在浏览器中也不能够调用
Node
内置API
3.3 Node 学习路径
3.3.1 Node 可以做什么
Node
作为一个 JavaScript 的运行环境,仅仅提供了基础的功能和 API
。然而,基于 Node
提供的这些基础能,很多强大
的工具和框架如雨后春笋,层出不穷,所以学会了 Node
,可以让前端程序员胜任更多的工作和岗位
- 基于 Express 框架,可以快速构建
Web
应用 - 基于 Electron 框架,可以构建跨平台的桌面应用
- 基于 restify 框架,可以快速构建
API
接口项目 - 读写和操作数据库、创建实用的命令行工具辅助前端开发、etc…
3.3.2 Node 学习路径
JavaScript 基础语法 --> Node.js
内置 API
模块(fs
、path
、http
等) --> 第三方 API
模块(express、mysql
等)
3.6 什么是终端
- 终端(英文:Terminal)是专门为开发人员设计的,用于实现人机交互的一种方式
- 作为一名合格的程序员,我们有必要识记一些常用的终端命令,来辅助我们更好的操作与使用计算机
4. fs
文件系统
4.1 fs
文件系统模块
fs
模块是Node.js
官方提供的、用来操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作需求
-
fs.readFile()
方法,用来读取指定文件中的内容 -
fs.writeFile()
方法,用来向指定的文件中写入内容
-
如果要在
JavaScript
代码中,使用fs
模块来操作文件,则需要使用如下的方式先导入它const fs = require('fs')
4.2 读取指定文件中的内容
4.2.1 fs.readFile()
的语法格式
使用 fs.readFile()
方法,可以读取指定文件中的内容,语法格式如下:
fs.readFile(path[, options], callback)
参数解读:
- 参数1:必选参数,字符串,表示文件的路径
- 参数2:可选参数,表示以什么编码格式来读取文件
- 参数3:必选参数,文件读取完成后,通过回调函数拿到读取的结果
4.2.2 fs.readFile()
的示例代码
// 1. 导入 fs 模块
const fs = require('fs')
// 2. 调用 fs.readFile() 方法读取文件
// 参数 1: 读取文件的存放路径
// 参数 2: 读取文件时候的编码格式,一般默认是 utf8
// 参数 3: 回调函数,拿到读取失败和成功的结果, err 以及 data
fs.readFile('./Tom.txt', 'utf8', function (err, data) {
// 3. err
// 如果读取失败,则 err 的值为 null
// 如果读取失败,则 err 的值为错误对象, data 的值为 undefined
console.log(err)
// 4. data 打印成功的结果
console.log(data)
})
4.2.3 判断文件是否读取成功
可以判断 err 对象是否为 null,从而知晓文件读取的结果
- 结果是 null ,说明文件读取成功
- 如果不为 null,说明文件读取失败
const fs = require('fs')
fs.readFile('./Tom.txt', 'utf8', function (err, data) {
// 判断 err 对象是否为 null
if (err) {
return console.log('文件读取失败:', err.message)
}
console.log('文件读取成功,内容是:', data)
})
4.3 向指定的文件中写入内容
4.3.1 fs.writeFile()
的语法格式
使用 fs.writeFile()
方法,可以向指定的文件中写入内容,语法格式如下
fs.writeFile(file, data[, options], callback)
参数解读:
- 参数1:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径
- 参数2:必选参数,表示要写入的内容
- 参数3:可选参数,表示以什么格式写入文件内容,默认值是
utf8
- 参数4:必选参数,文件写入完成后的回调函数
4.3.2 fs.writeFile()
的示例代码
// 1. 导入 fs 文件系统模块
const fs = require('fs')
// 2. 调用 fs.writeFile() 方法,写入文件的内容
// 参数 1:表示文件的存放路径
// 参数 2:表示要写入的内容
// 参数 3:回调函数
fs.writeFile('./Tom.txt', ' Jerry', function (err) {
// 3. err
// 3.1 如果文件写入成功,则 err 的值等于 null
// 3.2 如果文件写入失败,则 err 的值等于一个错误对象
console.log(err)
})
4.3.3 判断文件是否写入成功
可以判断 err 对象是否为 null,从而知晓文件写入的结果
const fs = require('fs')
fs.writeFile('./Tom.txt', 'Tom And Jerry', function (err) {
if (err) {
return console.log('文件写入失败', err.message)
}
console.log('文件写入成功')
})
4.4 fs
整理考试成绩案例
4.4.1 需求分析
使用 fs
文件系统模块,将素材目录下成绩 .txt
文件中的考试数据,整理到 成绩-ok.txt
文件中,整理前,成绩.txt
文件中的数据格式如下:
小红=99 小白=100 小黄=70 小黑=66 小绿=88
整理完成之后,希望得到的 成绩-ok.txt
文件中的数据格式如下:
小红: 99
小白: 100
小黄: 70
小黑: 66
小绿: 88
4.4.2 实现思路分析
- 导入需要的
fs
文件系统模块 - 使用
fs.readFile()
方法,读取素材目录下的成绩.txt
文件 - 判断文件是否读取失败
- 文件读取成功后,处理成绩数据
- 将处理完成的成绩数据,调用
fs.writeFile()
方法,写入到新文件成绩-ok.txt
中
4.4.3 实现步骤
- 读取成绩文件
// 1. 导入 fs 文件系统
const fs = require('fs')
// 2.调用 fs.rendFile() 读取文件的内容
fs.readFile('./成绩.txt', 'utf8', function (err, data) {
// 3. 判断是否读取成功
if (err) {
return console.log('读取文件失败!', err.message)
}
console.log('读取文件成功', data)
})
- 处理成绩
// 1. 导入 fs 文件系统
const fs = require('fs')
// 2.调用 fs.rendFile() 读取文件的内容
fs.readFile('./成绩.txt', 'utf8', function (err, data) {
// 3. 判断是否读取成功
if (err) {
return console.log('读取文件失败!', err.message)
}
// 4.1 将成绩按照空格进行分割
const oldArr = data.split(' ')
// 4.2 循环分割后的数组,对每一项数据,进行字符串的替换操作
const newArr = []
oldArr.forEach(item => {
// console.log(item)
newArr.push(item.replace('=', ': '))
})
// 4.3 将新数组中的每一项,进行合并,得到一个新的字符串
const newStr= newArr.join('\r\n')
console.log(newStr)
})
- 将整理好的成绩写入到新文件
// 1. 导入 fs 文件系统
const fs = require('fs')
// 2.调用 fs.rendFile() 读取文件的内容
fs.readFile('./成绩.txt', 'utf8', function (err, data) {
// 3. 判断是否读取成功
if (err) {
return console.log('读取文件失败!', err.message)
}
// 4.1 将成绩按照空格进行分割
const oldArr = data.split(' ')
// 4.2 循环分割后的数组,对每一项数据,进行字符串的替换操作
const newArr = []
oldArr.forEach(item => {
// console.log(item)
newArr.push(item.replace('=', ': '))
})
// 4.3 将新数组中的每一项,进行合并,得到一个新的字符串
const newStr= newArr.join('\r\n')
// console.log(newStr)
fs.writeFile('./成绩-ok.txt', newStr, function (err) {
if (err) {
return console.log('文件写入失败' + err.message)
}
console.log('成绩写入成功')
})
})
5. fs
路径问题
5.1 fs
模块路径动态拼接的问题
在使用 fs
模块操作文件时,如果提供的操作路径是以 ./
或 ../
开头的相对路径时,很容易出现路径动态拼接错误的问题
原因:代码在运行的时候,会以执行 node 命令时所处的目录
,动态拼接出被操作文件的完整路径
解决方案:在使用 fs
模块操作文件时,直接提供完整的路径,不要提供 ./
或 ../
开头的相对路径,从而防止路径动态拼接的问题
5.2 使用完整路径替换相对路径
使用完整路径替换相对路径,但这种写法移植性比较差,不利于后期的维护
const fs = require('fs')
fs.readFile('F:\\001 - 双元大课程\\009 - 服务器编程node\\003 - Node Code\\Day_001\\Tom.txt', 'utf8', function (err, data) {
// 判断 err 对象是否为 null
if (err) {
return console.log('文件读取失败:', err.message)
}
console.log('文件读取成功,内容是:', data)
})
5.3 使用 __dirname
解决路径拼接问题
__dirname
属性 Node
给提供的一个全局的属性,表示当前文件所处的目录
const fs = require('fs')
// __dirname 属性解决路径拼接问题
fs.readFile(__dirname + '/Tom.txt', 'utf8', function (err, data) {
// 判断 err 对象是否为 null
if (err) {
return console.log('文件读取失败:', err.message)
}
console.log('文件读取成功,内容是:', data)
})
6. path
路径模块
6.1 什么是 path 路径模块
path
模块是Node.js
官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理需求,例如:
-
path.join()
方法,用来将多个路径片段拼接成一个完整的路径字符串 -
path.basename()
方法,用来从路径字符串中,将文件名解析出来
-
如果要在 JavaScript 代码中,使用 path 模块来处理路径,则需要使用如下的方式先导入它
const path = rquire('path')
6.2 path 路径拼接
6.2.1 path.join()
的语法格式
使用 path.join()
方法,可以把多个路径片段拼接为完整的路径字符串,语法格式如下
path.join([...paths])
参数解读:
...paths
路径片段的序列- 返回值:
6.2.2 path.join()
的代码示例
使用 path.join()
方法,可以把多个路径片段拼接为完整的路径字符串
注意:今后凡是涉及到路径拼接的操作,都要使用 path.join()
方法进行处理。不要直接使用 + 进行字符串的拼接
const fs = require('fs')
const path = require('path')
// 使用 path.join() 做路径分割
fs.readFile(path.join(__dirname, '/Tom.txt'), 'utf8', function (err, data) {
// 判断 err 对象是否为 null
if (err) {
return console.log('文件读取失败:', err.message)
}
console.log('文件读取成功,内容是:', data)
})
6.3 获取路径中的文件名
6.3.1 path.basename()
的语法格式
使用 path.basename()
方法,可以获取路径中的最后一部分,经常通过这个方法获取路径中的文件名,语法格式如下
path.basename(path[, ext])
参数解读:
- path 必选参数,表示一个路径的字符串
- ext 可选参数,表示文件扩展名
- 返回: 表示路径中的最后一部分
6.3.2 path.basename()
的代码示例
使用 path.basename()
方法,可以从一个文件路径中,获取到文件的名称部分
const path = require('path')
const fpath = '/a/b/c/d/index.html' // 文件的存放路径
var fullName = path.basename(fpath)
console.log(fullName) // index.html 打印出文件的名称
var extName = path.basename(fpath, '.html')
console.log(extName) // index 打印文件的名称,但是忽略后缀名
6.4 获取路径中的文件扩展名
6.4.1 path.extname()
的语法格式
使用 path.extname()
方法,可以获取路径中的扩展名部分,语法格式如下
path.extname(path)
参数解读:
path
必选参数,表示一个路径的字符串- 返回: 返回得到的扩展名字符串
6.4.2 path.extname()
的代码示例
使用 path.extname()
方法,可以获取路径中的扩展名部分
const path = require('path')
const fpath = '/a/b/c/d/index.html' // 文件的存放路径
var fullName = path.extname(fpath)
console.log(fullName) // .html 返回文件的拓展名
7. 时钟案例
7.1 案例介绍
- 案例要实现的功能
- 案例的实现步骤
- 创建两个正则表达式,分别用来匹配
<style>
和<script>
标签 - 使用
fs
模块,读取需要被处理的HTML
文件 - 自定义
resolveCSS
方法,来写入index.css
样式文件 - 自定义
resolveJS
方法,来写入index.js
脚本文件 - 自定义
resolveHTML
方法,来写入index.html
文件
7.2 案例实现步骤
- 导入需要的模块并创建正则表达式
// 1.1 导入 fs 文件系统模块
const fs = require('fs')
// 1.2 导入 path 路径处理模块
const path = require('path')
// 1.3 匹配 <style></style> 标签的正则
// \s 表示空白字符 \S 表示非空字符 * 表示匹配任意次
const regStyle = /<style>[\s\S]*<\/style>/
// 1.4 匹配 <script></script> 标签的正则
const regScript = /<script>[\s\S]*<\/script>/
- 使用
fs.readFile
方法读取html
文件的内容
// 1.1 导入 fs 文件系统模块
// 其他代码略……
// 2.1 调用 fs.readFile() 方法读取文件
fs.readFile(path.join(__dirname, '/index.html'), 'utf8', function (err, data) {
// 2.2 读取 html 文件失败
if (err) return console.log('读取文件失败' + err.message)
// 2.3 读取文件成功后,调用对应的 3 个方法,解析出 css、js、html 内容
})
- 自定义
resolveCss
方法提取样式表文件
// 3.1 处理 css 样式
function resolveCss(htmlStr) {
// 3.2 使用正则提取页面中的 <style></style>
const r1 = regStyle.exec(htmlStr)
// 3.3 将提取出来的样式字符串,做进一步的处理
const newCss = r1[0].replace('<style>', '').replace('</style>', '')
// 3.4 将提取出来的 css 样式,写入到 index.css 文件中
fs.writeFile(path.join(__dirname, '/style/index.css'), newCss, err => {
if (err) return console.log('写入 css 样式表失败 !', err.message)
console.log('写入文件成功')
})
}
- 自定义
resolveJS
方法
// 4.1 处理 js 脚本
function resolveJs (htmlStr) {
// 4.2 使用正则表达式提取出页面中的 <script></script> 标签
const r2 = regScript.exec(htmlStr)
// 4.3 将提取出来的脚本字符串,做进一步处理
const newJs = r2[0].replace('<script>', '').replace('</script>', '')
// 4.4 将提取出来的 js 脚本,写入到 index.js 文件中
fs.writeFile(path.join(__dirname, '/script/index.js'), newJs, err => {
if (err) return console.log('写入 JavaScript 脚本失败', err.message)
console.log('写入脚本文件成功 !')
})
}
- 自定义
resolveHTML
方法
// 5.1 处理 html 文件函数
function resolveHtml(htmlStr) {
// 5.2 使用字符串的 replace 方法,把内嵌的 <script> 和 <style> 标签,替换为外联的 <link> 和 <script> 标签
const newHtml = htmlStr
.replace(regStyle, '<link rel="stylesheet" href="./style/index.css" />')
.replace(regScript, '<script src="./script/index.js"></script>')
// 5.3 将替补完成之后的 html 代码,写入到 index.html 中
fs.writeFile(path.join(__dirname, '/time.html'), newHtml, err => {
if (err) return console.log('写入文件失败', err.message)
console.log('写入 html 页面成功 !')
})
}
- 案例的两个注意点
fs.writeFile()
方法只能用来创建文件,不能用来创建路径- 重复调用
fs.writeFile()
写入同一个文件,新写入的内容会覆盖之前的旧内容
正则表达式
- var reg = / / 初始化正则表达式
- /^ $/ 匹配开头和结尾
- reg.test(‘字符串’) 判断字符串是否符合正则表达式
- [a-zA-Z0-9] 匹配其中的某一个
- a* 匹配0次或多次
- a+ 匹配1次或多次
- a? 匹配0次或1次
- a{5} 匹配5次
- a{5, 10} 匹配5-10次
- \d 数字 \D 非数字
- \w 数字字母下划线
- \s 空白字符 \S 非空白字符
- [\s\S]* 所有字符
- str.replace(reg, ‘****’) 正则替换
- reg.exec(字符串) 正则提取, 返回一个数组,数组第一项就是提取的内容