目标:
- 能够知道什么是Nodejs
- 能够知道Node.js 可以做什么
- 能够说出 Nodejs 中的JavaScript的组成部分
- 能够使用fs模块读写操作文件
- 能够使用path模块处理路径
- 能够使用http模块写一个基本的web服务器
1. DOS基础操作
1.1 常用的命令
1、怎么打开DOS命令窗口(小黑屏)、CMD 窗口、终端、shell
---打开菜单—-运行---->cmd--->回车 ;或者 win+r,输入cmd,回车。
2、什么是DOS命令?
可以完全完成文件的新建、编辑、保存、删除等一系列操作。
3、mkdir abc(非必须掌握)
创建一个目录,起名abc cd 目录名——进入到指定目录; md 目录名——创建一个文件夹; rd 目录名——删除一个文件夹
直接上箭头可以快速定位到上一次执行的命令
tab 键,能够快捷补全路径
esc 键,能够快速清空当前已输入的命令
cls 清屏
4、切换盘符
直接输入盘符就行:
c:回车
d:回车
5、切换目录(非常重要,必修掌握)
使用cd命令来完成命令的切换。(change directory)
语法格式是:cd 路径
路径包括相对路径和绝对路径。
在window系统中路径起点是盘符的都是绝对路径: c:\User\Administrator
相对路径是相对于当前而言,从当前所在的位置作为起点,一定不会以盘符为起点
注意:
cd .. 回到上级路径
cd \ 直接回到根路径
cd . 代表当前路径。(cd命令用不着。以后配置环境变量的时候一个点有用处)
6、dir 查看当前目录的所有文件
7、exit 退出DOS命令窗口
8、del命令,删除一个或多个文件夹
删除T1.class文件:del T1.class
删除所有以class结尾的文件,支持模糊匹配:del *class
9、怎么查看本机的ip地址?
ipconfig(ip地址的配置信息)
ipconfig /all 查看更详细的网络信息
10、怎么查看两台计算机是否可以正常通信?
ping命令
语法格式:
ping ip地址
ping 域名
ping www.baidu.com
ping 61.135.169.121 (是百度的ip地址)
ping 61.135.169.121 -t (-t参数表示一直ping,可以查看网络是否稳定)
ctrl+c 组合键 强行终止一个正在执行的命令
11、文本编辑快捷键(非常重要,必修掌握,少用鼠标,多用组合键)
常用的组合键:
复制 ctrl+c
粘贴 ctrl+v
剪切 ctrl+x
保存 ctrl+s
撤销 ctrl+z
重做 ctrl+y
全选 ctrl+a
查找 ctrl+f
截图 Alt+A
12、光标在行首或行尾,想要选中一行
shift+fn+home/end
回到文件头或文件尾
ctrl+fn+home/end
选中一个单词:鼠标双击(或ctrl+shift+左/右箭头)
选中一行:鼠标三击
13、环境变量(windowe采统中的变量)
此电脑—右键属性—高级系统设备—高级—环境变量
path环境变量中保存的是一个一个的路径,路径之间使用;隔开
作用:当我们在命令行窗口中调用一个命令,或访问一个文件时,系统会先在当前文件夹中寻找,如果找不到则依次去path的路径下寻找,如果找到则直接使用,如果没有找到则继续向下一个路径去寻找,如果所有的路径中都没有找到,则报错。
可以将一些常用的文件或程序的路径添加到path下,这样我们就可以在任意位置来访问这些文件了
1. 初识 Node.js
1.1 Node.js 简介
- 浏览器是 JavaScript 的前端运行环境。
- Node.js 是 JavaScript 的后端运行环境。
- Node.js 无法调用 DOM 和 BOM 等浏览器内置API.
1.2 Node.js 可以做什么
Node.js 作为一个JavaScript的运行环境,仅仅提供了基础的功能和API。然而,基于Node.js 提供的这些基础功能,很多强大的工具和框架如雨后春笋,层出不穷,所以学会了 Nodejs,可以让前端程序员胜任更多的工作和岗位:
① 基于Express 框架(http://www.expressjs.com.cn/),可以快速构建 Web 应用
② 基于 Electron 框架(https://electronjs.org/),可以构建跨平台的桌面应用
③ 基于restify 框架(http://restify.com/),可以快速构建API 接口项目
④ 读写和操作数据库、创建实用的命令行工具辅助前端开发、etc..
总之:Node.js 是大前端时代的“大宝剑”,有了 Node.js 这个超级buff的加持,前端程序员的行业竞争力会越来越强!
1.3 Node.js 学习路径
JavaScript 基础语法 + Node.js 内置 API 模块(fs、path、http等)+ 第三方 API 模块(express、mysql 等)
1.4 在Node.js 环境中执行 JavaScript 代码
-
打开终端(可以直接在目标文件地址栏输入cmd回车 。或者在目标文件 shift + 鼠标右键 选择打开powershell窗口)
- 输入 node 要执行的 js 文件的路径
2. fs 文件系统模块
2.1 什么是 fs 文件系统模块
fs模块是 Nodejs官方提供的、用来操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作需求。例如:
fs.readFile() 方法,用来读取指定文件中的内容
fs.writeFile() 方法,用来向指定的文件中写入内容
如果要在 JavaScript 代码中,使用 fs 模块来操作文件,则需要使用如下的方式先导入它:
const fs = require('fs')
2.2 读取指定文件中的内容
2.2.1 fs.readFile() 的语法格式
使用 fs.readFile() 方法,可以读取指定文件中的内容,语法格式如下:
fs.readFile(path[, options],callback)
参数1:必选参数,字符串,表示文件的路径。
参数2:可选参数,表示以什么编码格式来读取文件。
参数3:必选参数,文件读取完成后,通过回调函数像到读取的结果。
// 1. 导入 fs 模块,来操作文件
const fs = require('fs');
// 2. 调用 fs.readfile() 方法读取文件
// 参数1:读取文件的存放路径
// 参数2:读取文件时采用的编码格式,默认utf8
// 参数3:回调函数,拿到读取失败和成功的结果 err dataStr
fs.readFile('./01.txt', 'utf8', function (err, dataStr) {
// 打印失败的结果,
// 如果读取成功,则err的值为 null
// 如果读取失败,则err的值为错误对象,dataStr的值为undefined
// console.log(err);
// console.log('---------------');
// 打印成功的结果
// console.log(dataStr);
if (err) {
console.log('文件读取失败' + err.message);
} else {
console.log('文件读取成功,内容是:' + dataStr);
}
})
2.2.1 fs.writeFile() 的语法格式
使用fs.writeFile() 方法,可以向指定的文件中写入内容,语法格式如下:
fs.writeFile(file, data[, options], callback)
参数1:必选参数,需要指定一个文件路径的字符串,表示文件的存放路径。
参数2:必选参数,表示要写入的内容
参数3:可选参数,表示以什么格式写入文件内容,默认值是utf8。
参数4:必选参数,文件写入完成后的回调函数。
const fs = require('fs');
fs.writeFile('./02.txt', 'abcd', function (err) {
// 如果文件写入成功,则err的值等于null
// 如果文件写入失败,则err的值是一个错误对象
// console.log(err);//null
if (err) {
return console.log('文件写入失败!' + err.message);
} else {
console.log('文件写入成功!');
}
})
//写了 return 可以写 else 也可以不写,没写return一定要else
新写入的内容会覆盖旧的内容!
考试成绩整理案例:
// 一、导入fs模块
const fs = require('fs')
// 二、调用fs.readFile() 读取文件内容
fs.readFile('./03.成绩.txt', 'utf8', function (err, data) {
if (err) {
return console.log('读取失败!');
}
// console.log('读取成功!' + data);//读取成功!小红=90 小白=100 小蓝=60 小黑=99 小绿=77
// 1. 先把成绩的数据按照空格进行分割,存到一个数组里面
const arrOld = data.split(' ') //用const声明后面不能对arrOld进行修改
// console.log(arrOld);//[ '小红=90', '小白=100', '小蓝=60', '小黑=99', '小绿=77' ]
// 2. 循环分割后的数组,对每一项数据,进行字符串的替换操作
const arrNew = []
arrOld.forEach(items => {
arrNew.push(items.replace('=', ':'))
});
// console.log(arrNew);//[ '小红:90', '小白:100', '小蓝:60', '小黑:99', '小绿:77' ]
// 3. 把新数组中的每一项,进行合并,得到一个新的字符串
const newStr = arrNew.join('\n') // 写 \r\n 也可以
// console.log(newStr);
// 三、调用fs.writeFile() 把处理完毕的成绩,写入到新文件中(不能写在外面,写在外面用不了newStr)
fs.writeFile('./03.整理后的成绩.txt', newStr, function () {
if (err) {
return console.log('写入文件失败!');
}
console.log('写入文件成功!');
})
})
2.3 fs 模块 - 路径动态拼接的问题
在使用fs模块操作文件时,如果提供的操作路径是以 ./ 或 ../ 开头的相对路径时,很容易出现路径动态拼接错误的问题。
原因:代码在运行的时候,会以执行node命令时所处的目录,动态拼接出被操作文件的完整路径。
解决方案:在使用 fs 模块操作文件时,直接提供完整的路径,不要提供 ./ 或 ../ 开头的相对路径,从而防止路径动态拼接的问题。
const fs = require('fs');
// 直接提供完整的路径, 移植性非常差,不利于维护
// fs.readFile('D:\\gongyong\\web\\autostudy\\7. Node.js\\1-code\\01.txt', 'utf8', function (err, dataStr) {
// if (err) {
// console.log('文件读取失败' + err.message);
// } else {
// console.log('文件读取成功,内容是:' + dataStr);
// }
// })
// __dirname 表示当前文件所处目录(以后都这样写)
fs.readFile(__dirname + '/01.txt', 'utf8', function (err, dataStr) {
if (err) {
console.log('文件读取失败' + err.message);
} else {
console.log('文件读取成功,内容是:' + dataStr);
}
})
//后面会学到如何代替 + 拼接路径
3. path 路径模块
3.1 什么是 path 路径模块
path 模块是 Node.js 官方提供的、用来处理路径的模块。它提供了一系列的方法和属性,用来满足用户对路径的处理需求。例如:
path.join() 方法,用来将多个路径片段拼接成一个完整的路径字符串
path.basename() 方法,用来从路径字符串中,将文件名解析出来
如果要在JavaScript代码中,使用path模块来处理路径,则需要使用如下的方式先导入它:
const path = require('path')
3.2 路径拼接
3.2.1 path.join() 的语法格式
使用 path.jion() 方法,可以将多个路径片段拼接成一个完整的路径字符串
path.join([...paths])
- ...paths <string> 路径片段的序列;
- 返回值:<string>
const path = require('path')
const fs = require('fs')
// ../ 会覆盖掉(抵消)前面一个路径,(有几个 ../ 就抵消几个路径)
// const pathStr = path.join('/a', '/b/c', '../', 'd', 'e')
// console.log(pathStr);// \a\b\d\e
fs.readFile(path.join(__dirname, '/01.txt'), 'utf8', function (err, data) {
if (err) {
return console.log('读取失败!');
}
console.log('读取成功!' + data);
})
注意:今后凡是遇到路径拼接的问题,都要使用 path.join() 方法进行处理。不要直接使用 + 进行字符串的拼接
3.3 获取路径中的文件名
3.3.1 path.basename() 的语法格式
path.basename(paths[,ext])
- path <string> 必选参数,表示一个路径的字符串
- ext <string> 可选参数,表示文件扩展名
- 返回:<string> 表示路径中的最后一部分
3.4 获取路径中的文件扩展名
3.4.1 path.extname() 的语法格式
path.extname(path)
- path <string> 必选参数,表示一个路径的字符串
- 返回:<string> 返回得到的扩展名字符串
// 导入path模块
const path = require('path')
// 文件的存放路径
const fpath = 'a/b/c/index.html'
const fext = path.extname(fpath)
console.log(fext); //.html
百度换肤案例仿时钟案例:
// 1.1 导入fs文件系统模块
const fs = require('fs');
// 1.2 导入 path模块
const path = require('path');
// 1.3 定义正则表达式,分别匹配 <style></style> 和 <script></script> 标签
const regStyle = /<style>[\s\S]*<\/style>/; //为免斜杆冲突,要加一个反斜杠
const regScript = /<script>[\s\S]*<\/script>/;
// 2.1 调用fs.readFile()读取文件
fs.readFile(path.join(__dirname, '/模仿时钟案例素材/02-百度换肤.html'), 'utf8', function (err, dataStr) {
// 如果读取失败
if (err) {
return console.log('读取文件失败!' + err.message);
}
// console.log('读取文件成功!' + dataStr);
// 2.2 读取文件成功后,调用对应的三个方法,分别拆解出css、js、html文件
resolveCss(dataStr);
resolveJs(dataStr);
resolveHtml(dataStr);
})
// 3.1 处理css脚本
function resolveCss(htmlStr) {
// 3.2 利用正则方法exec提取需要的内容
const r1 = regStyle.exec(htmlStr);
// console.log(r1);
// 3.3 将提取出来的样式字符串,进行替换操作
const newCss = r1[0].replace('<style>', '').replace('</style>', '');
// console.log(newCss);
// 3.4 调用fs.writeFile()将提取的样式写入 clock 文件中 index.css文件
fs.writeFile(path.join(__dirname, '/clock/index.css'), newCss, function (err) {
if (err) {
console.log('写入css脚本失败!');
}
console.log('写入css脚本成功!');
})
}
// 4.1 处理js脚本
function resolveJs(htmlStr) {
// 4.2 利用正则方法exec提取需要的内容
const r2 = regScript.exec(htmlStr);
// console.log(r2);
// 4.3 将提取出来的样式字符串,进行替换操作
const newJs = r2[0].replace('<script>', '').replace('</script>', '');
// console.log(newJs);
// 4.4 调用fs.writeFile()将提取的样式写入 clock 文件中 index.js文件
fs.writeFile(path.join(__dirname, '/clock/index.js'), newJs, function (err) {
if (err) {
console.log('写入js脚本失败!');
}
console.log('写入js脚本成功!');
})
}
// 5.1 处理html脚本
function resolveHtml(htmlStr) {
// 5.2 使用字符串的 replace,把内嵌的style和script替换成外联的链接
const newHtml = htmlStr
.replace(regStyle, '<link rel="stylesheet" href="./index.css">')
.replace(regScript, '<script src="./index.js"></script>');
// console.log(newHtml);
// 5.3 调用fs.writeFile()将得到的html写入 clock 文件中 index.html文件
fs.writeFile(path.join(__dirname, '/clock/index.html'), newHtml, function (err) {
if (err) {
console.log('写入html页面失败!');
}
console.log('写入html页面成功!');
})
}
4. http 模块
4.1 什么是http模块
回顾:什么是客户端,什么是服务器?
在网络节点中,负责消费资源的电脑,叫做客户端;负责对外提供网络资源的电脑,叫做服务器。
http模块是 Node.js 官方提供的、用来创建 web服务器的模块。通过http模块提供的 http.createServer()方法,就能方便的把一台普通的电脑,变成一台Web服务器,从而对外提供 Web 资源服务。
如果要希望使用http模块创建Web服务器,则需要先导入它:
const http = require("http")
服务器和普通电脑的区别在于,服务器上安装了web服务器软件,例:IIS、Apache 等。通过安装这些服务器软件一台普通的电脑变成一台web服务器。
在Nodes中,我们不需要使用IS、Apache等这些第一方web服务器软件。因为我们可以基于Node.js 提供的 http 模块, 通过几行简单的代码 就能轻松的手写一个服务器软件,从而对外提供web服务。
4.2 服务器相关的概念
4.2.1 IP地址
IP地址就是互联网上每台计算机的唯一地址,因此IP地址具有唯一性。如果把”个人电脑”比作”一台电话”,那么 “1P地址” 就相当于 “电话号码”,只有在知道对方 IP 地址的前提下,才能与对应的电脑之间进行数据通信。
IP 地址的格式:通常用“点分十进制”表示成 (a.b.c.d) 的形式,其中,abcd 都是0~255之间的十进制整数。例如:用点分十进表示的IP地址(192.168.1.1)
注意:
① 互联网中每台Web 服务器,都有自己的IP 地址,例如:大家可以在Windows的终端中运行ping www.baidu.com 命令,即可查看到百度服务器的IP 地址。
在开发期间,自己的电脑既是一台服务器,也是一个客户端,为了方便测试,可以在自己的浏览器中输入127.0.0.1 或者 localhost 这个 IP地址,就能把自己的电脑当做一台服务器进行访问了。
域名服务器就是提供IP地址和域名之间转换服务的服务器。
4.2.2 端口号
- 每个端口号不能同时被多个web服务占用
- 在实际应用中,URL 中的 80 端口可以被省略
4.3 创建最基本的 web 服务器
4.3.1. 创建 web 服务器的基本步骤
- 步骤1: 导入http模块
const http = require("http")
- 步骤2: 创建web服务器实例
//调用 createServer() 方法创建web服务器实例 const server = http.createServer()
- 步骤3:为服务器实例绑定request 事件,监听客户端的请求
// 使用服务器实例的 .on() 方法,为服务器绑定一个 request 事件 server.on('request' , (req, res) => { //只要有客户端请求我们自己的服务器,就会触发 request 事件,从而调用这个事件处理函数 console.log('Someone visit our web server'); })
- 步骤4:启动服务器
//调用 server.listen(端口号,cb回调) 方法,即可启动web服务器
server.listen(80, () => {
console.log('http server running at http://127.0.0.1');
})
实例: VS 顶部点终端,选新建终端,下面像 在控制台一样输入,注意:端口号不能重复 ctrl + c 停止服务器 如果更改了代码内容,要结束终端再重新打开。
// 1. 导入http模块
const http = require('http');
// 2. 创建web服务器实例
const server = http.createServer();
// 3. 为服务器实例绑定 request 事件,监听客户端的请求
server.on('request', function (req, res) {
console.log('Someone visit our web server');
})
// 4. 启动服务器
server.listen(80, function () {
console.log('http server running at http://127.0.0.1:80');//如果是80就可以省略
})
4.3.2 req 请求对象
// 导入 http 模块
const http = require('http');
// 创建服务器
const server = http.createServer()
// 绑定request事件
// req是请求对象,包含了与客户端相关的数据和属性
server.on('request', (req) => {
// req.url 是客户请求的 URL 地址
const url = req.url;
// req.method 是客户端请求的method类型
const method = req.method;
const str = `Your request url is ${url},and request method is ${method}`;
console.log(str);
})
// 启动服务器
server.listen(80, () => {
console.log('server running at http://127.0.0.1');
})
4.3.3 res 响应对象
// 导入 http 模块
const http = require('http');
// 创建服务器
const server = http.createServer()
// 绑定request事件
// req是请求对象,包含了与客户端相关的数据和属性
server.on('request', (req, res) => {
// req.url 是客户请求的 URL 地址
const url = req.url;
// req.method 是客户端请求的method类型
const method = req.method;
const str = `Your request url is ${url},and request method is ${method}`;
console.log(str);
// 调用 res.end() 方法,向客户端响应一些内容
res.end(str); //在下面的终端复制地址在浏览器打开就可以看到内容(用的是get请求)
// (如果想要发一个post请求,去postman测试工具选择post方式)
})
// 启动服务器
server.listen(80, () => {
console.log('server running at http://127.0.0.1');
})
4.3.4 解决中文乱码问题
const http = require('http');
const server = http.createServer();
server.on('request', function (req, res) {
// 定义一个字符串。包含中文内容
const str = `请求的url地址是${req.url},请求的method类型是${req.method}`;
// res.end() 将内容相应给客户端
// 调用res.setHeader() 方法,设置 content-Type 响应头,解决中文乱码问题
res.setHeader('content-Type', 'text/html;charset=utf-8');//固定写法
res.end(str);
})
server.listen(80, function () {
console.log('server running at http://127.0.0.1');
})
4.4 根据不同的 url 响应不同的 http 内容
4.4.1 核心实现步骤
1. 获取请求的 url 地址
2. 设置默认的响应内容为 404 Not found
3. 判断用户请求的是否为 / 或 /index.html 首页
4. 判断用户请求的是否为 /about.html 关于页面
5. 设置 Content-Type 响应头,防止中文乱码
6. 使用 res.end() 把内容响应给客户端
实例:
const http = require('http');
const server = http.createServer();
server.on('request', function (req, res) {
// 获取请求的 url 地址
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>';
}
// 设置 Content-Type 响应头,防止中文乱码
res.setHeader('Content-Type', 'text/html;charset=utf-8');
// 使用 res.end() 把内容响应给客户端
res.end(content);
})
server.listen(80, function () {
console.log('server running at http://127.0.0.1');
})
4.4.2 案例 - 实现百度换肤的web服务器 :
1. 核心思路
- 把文件的实际存放路径,作为每个资源的请求 url 地址
2. 实现步骤
- 导入需要的模块
- 创建基本的web服务器
- 将资源的 请求 url 地址映射为 文件的存放路径
- 读取文件内容并响应给客户端
- 优化资源的请求路径
// 1. 导入需要的模块
// 1.1 导入http模块,用于创建服务器
const http = require('http');
// 1.2 导入fs模块,用于读取文件
const fs = require('fs');
// 1.3 导入path模块,用于处理路径问题
const path = require('path');
// 2.1 创建基本的web服务器
const server = http.createServer();
// 2.2 监听web服务器的request事件
server.on('request', function (req, res) {
// 3.1 获取到客户端请求的url地址
// /clock/index.html
// /clock/index.css
// /clock/index.js
const url = req.url;
// 3.2 将资源的 请求 url 地址映射为 文件的存放路径
// const fpath = path.join(__dirname, url);
// 5.1 预定义一个空白的文件存放路径
let fpath = '';
if (fpath === '/') {
fpath = path.join(__dirname, './clock/index.html');
} else {
// /index.html
// /index.css
// /index.js
fpath = path.join(__dirname, '/clock', url);
}
// 4.1 根据映射过来的路径读取文件内容并响应给客户端
fs.readFile(fpath, 'utf8', (err, dataStr) => {
// 4.2 读取失败,向客户端响应固定的“错误消息”
if (err) {
return res.end('404 Not found');
}
// 4.3 读取成功,将读取成功的内容响应给客户端
// res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.end(dataStr)
})
})
// 2.3 启动服务器
server.listen(80, function () {
console.log('server running at http://127.0.0.1');
})
注意: 由于使用的案例由图片构成,所以显示不出来,但审查元素是成功的。虽然但是,我也不知道为啥图片不能显示,但代码应该是没有错的...