铺垫
- 两个问题
-
为什么浏览器可以运行JavaScript? 因为浏览器中有JS解析引擎,各个浏览器使用的解析引擎不一样,其中Chrome浏览器使用的V8引擎性能最好。
-
为什么JavaScript可以操作DOM和BOM? 因为每个浏览器都内置了DOM、BOM甚至AJAX相关的API函数。因此JS可以调用它们。
- 运行环境 运行环境是指代码正常运行所必需的必要环境。
例如Chrome浏览器运行环境,包括V8引擎和内置API(例如DOM、BOM、Canvas、XMLHttpRequest、JS内置对象等等)。
简介
-
什么是Node.js Node.js是一个基于Chrome V8引擎的JavaScript运行环境。
-
Node.js运行环境 Node.js运行环境包括V8引擎和内置API(例如fs、path、http、JS内置对象、querystring等等)。
注意浏览器是JavaScript的前端运行环境,Node.js是JavaScript的后端运行环境。在Node.js运行环境中无法调用DOM、BOM、AJAX等浏览器内置的API。
- Node.js的使用
- 编写好一段JS代码
win+R输入cmd打开终端- 用
cd命令进入到代码所在目录下 - 输入
node 文件名运行该JS代码 也可以在代码所在目录下直接按住shift键再点鼠标右键打开Powershell窗口。
Powershell和cmd都是windows系统下的终端,只不过Poweshell是cmd的升级版,更新、功能也更多。
fs 模块
- fs.readFile()
该方法用于读取文件,并有三个参数
参数1:要读取文件的存放路径
参数2:读取文件时采取的编码格式,一般默认指定utf8(可选)
参数3:读取操作结束后的回调函数,参数是读取失败和读取成功的结果
// 导入 fs 模块
const fs = require('fs')
fs.readFile('./test.txt', 'utf8', function (err, dataStr) {
// 若读取失败则err是一个错误对象,dataStr是undifined
// 若读取成功则err是null,dataStr是读取的那个文件里的内容
console.log(err);
console.log(dataStr);
})
- fs.writeFile()
该方法用于向文件中写入内容,并有四个参数
参数1:要写入内容的文件的存放路径
参数2:要写入的内容,该参数只能传入字符串,并且会覆盖之前文件中已有的内容
参数3:写入文件时采取的编码格式,一般默认指定utf8(可选)
参数4:写入操作结束后的回调函数,参数是写入失败的结果
// 导入 fs 模块
const fs = require('fs')
fs.writeFile('./test.txt', ' hello fs!', 'utf-8', function (err) {
// 若写入失败则err是一个错误对象
// 若写入成功则err是null
if (err === null) {
console.log('文件写入成功!');
}
else {
console.log('文件写入失败!');
console.log(err);
}
})
补充三个函数方法:
let newArr = someStr.split('规定字符') // 把字符串用规定的字符分割成数组let newStr = someArr.join('规定字符') // 把数组中的每个元素用规定的字符拼接成字符串someStr.replace('旧字符', '新字符') // 自动搜索字符串里的旧字符,并替换成新字符
- 路径问题
不管我们用
fs.readFile()还是fs.writeFile(),都要使用到文件的路径,我们在传入一个路径作为参数的时候可以用相对路径和绝对路径,但是相对路径可能会发生一些错误,使用绝对路径又损失了移植性。
所以我们通常会使用一个对象__dirname来表示文件执行的当前目录。
fs.readFile(__dirname + '/test.txt', 'utf-8', function (err, dataStr) {
if (err) {
console.log('读取错误!');
console.log(err);
}
else {
console.log(dataStr);
}
})
path 模块
- path.join() 该方法用于拼接路径
// 导入 path 模块
const path = require('path')
const pathStr = path.join(__dirname, '/test.txt')
console.log(pathStr) // C:\Users\Citizen7\Desktop\moonshot\MS6_Node_1\test.txt
- path.basename() 该方法用于返回一个文件路径的最后一个路径,即文件名
// 导入 path 模块
const path = require('path')
const fpath = 'C:/Users/Citizen7/Desktop/moonshot/MS6_Node_1/test.txt'
console.log(path.basename(fpath)) // test.txt
console.log(path.basename(fpath, '.txt')) // test
- path.extname() 该方法用于返回一个文件路径的拓展名
// 导入 path 模块
const path = require('path')
const fpath = 'C:/Users/Citizen7/Desktop/moonshot/MS6_Node_1/test.txt'
console.log(path.extname(fpath)) // .txt
案例 1
将一个包含有CSS、JS和HTML代码的HTML页面分割成CSS、JS、HTML三个部分,并分别放入三个文件中。
// 导入模块
const fs = require('fs');
const path = require('path');
// 定义正则表达式
const regStyle = /<style>[\s\S]*<\/style>/;
const regScript = /<script>[\s\S]*<\/script>/;
// 读取文件
fs.readFile(path.join(__dirname, '/aim.html'), 'utf-8', function (err, dataStr) {
if (err) {
return console.log('读取出错!' + err.message);
}
else {
resolveCSS(dataStr);
resolveJS(dataStr);
resolveHTML(dataStr);
}
});
// 处理CSS的方法
function resolveCSS(htmlStr) {
// 使用正则提取需要的内容
let cssArr = regStyle.exec(htmlStr);
// 将提取出来的字符串,进行字符串的replace替换操作
let newCSS = cssArr[0].replace('<style>', '').replace('</style>', '');
// 将处理完的CSS字符串写入到新的文件中
fs.writeFile(path.join(__dirname, '/aim/index.css'), newCSS, 'utf-8', function (err) {
if (err) {
return console.log('写入CSS出错!' + err.message);
}
else {
console.log('写入CSS成功!');
}
})
}
// 处理JS的方法
function resolveJS(htmlStr) {
// 使用正则表达式提取<script>标签里的内容,放入数组里
let jsArr = regScript.exec(htmlStr);
// 将提取出来的字符串(即数组的第一个元素)进行replace替换操作
let newJS = jsArr[0].replace('<script>', '').replace('</script>', '');
// 将处理完成的字符串写入新的文件中
fs.writeFile(path.join(__dirname, '/aim/index.js'), newJS, 'utf-8', function (err) {
if (err) {
return console.log('写入JS出错!' + err.message);
}
else {
console.log('写入JS成功!');
}
})
}
// 处理HTML方法
function resolveHTML(htmlStr) {
// 把原始的html页面中的css和js部分替换掉
let newHTML = htmlStr
.replace(regStyle, '<link rel="stylesheet" href="./index.css" />')
.replace(regScript, '<script src="./index.js"></script>');
// 写入新的文件中
fs.writeFile(path.join(__dirname, '/aim/index.html'), newHTML, 'utf-8', function (err) {
if (err) {
console.log('写入HTML出错!' + err.message);
}
else {
console.log('写入HTML成功!');
}
})
}
http 模块
- 服务器
-
IP地址 互联网中的每一台计算机都有一个唯一的IP地址,每台计算机之间的通信都必须通过IP地址来访问,IP地址是形如
127.112.41.1的数字。在我们开发过程中127.0.0.1就是我们本机的IP地址。 -
域名 IP地址固然可以唯一标识每一台计算机,但是毕竟不好记忆,所以我们可以为每一个IP地址起一个域名,形如
www.juejin.cn,它对应的IP地址就是220.185.186.124(可以在终端中用ping 域名命令来查看域名的IP地址)。即使我们有了域名,也不能直接通过域名来访问一台服务器,它只是方便人们使用,在互联网中必须经过 域名服务器(DNS)来将域名与IP地址一一对应起来,再通过IP地址去访问服务器。 -
端口 一台作为服务器的计算机有一个IP地址(域名),但这个服务器内部可以有多种服务,客户端想要指定访问这台服务器的某一种服务,就需要在IP地址或者域名后面指定一个端口号,每一个端口号对应一个不同的服务。
- 创建简单的web服务器
// 导入 http 模块
const http = require('http');
// 创建 web 服务器实例
const server = http.createServer();
// 为服务器实例绑定事件,监听客户端的请求
server.on('request', (req, res) => {
console.log('Someone visit our web server.');
// req 是客户端的请求对象,里面包含了与客户端相关的数据和属性
console.log(req.url); // url 属性存放了请求的 url
console.log(req.method); // method 属性存放了请求的方式
// res 是服务器的响应对象,里面包含了与服务器相关的数据和属性
let str = `Your request url is ${req.url}, and request method is ${req.method}`;
res.end(str); // res.end() 函数会将指定的内容响应到页面上,并结束此次响应
});
// 启动服务器
server.listen(80, () => {
console.log('Server running at http://127.0.0.1:80.');
});
需要注意,当res.end()向客户端发送的内容中有中文字符时,实际显示的时候会出现乱码,这时候需要设置一个响应头res.setHeader('Content-Type', 'text/html; charset=utf-8')
- 动态响应内容 根据不同的请求URL,响应不同的内容
const http = require('http');
const server = http.createServer();
// 当服务器被请求时执行以下函数
server.on('request', (req, res) => {
let url = req.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(8080, () => {
console.log('Server running at http://127.0.0.1:8080.');
});
案例 2
综合了上述三个模块的使用
// 导入模块
const http = require('http')
const fs = require('fs')
const path = require('path')
// 创建 web 服务器
const server = http.createServer()
// 监听服务器的请求事件
server.on('request', (req, res) => {
// 获取客户端请求的url地址
const url = req.url
// 把请求的url地址映射为本地文件的存放路径
let fpath = ''
if (url === '/') {
// 如果客户端请求的是根目录,则默认是index.html
fpath = path.join(__dirname, '/aim/index.html')
}
else {
// 如果客户端请求的不是根目录,也提前写上 /aim 目录
fpath = path.join(__dirname, '/aim', url)
}
// 设置响应头
res.setHeader('Content-Type', 'text/html; charset=utf-8')
// 读取本地文件并响应到页面
fs.readFile(fpath, 'utf-8', (err, dataStr) => {
if (err) {
return res.end('<h1>404 Not Found.</h1>')
}
else {
res.end(dataStr)
}
})
})
// 启动服务器
server.listen(8081, () => {
console.log('Server running at http://127.0.0.1:8081.')
})