深入浅出Node.js-1(node.js入门)
全新专栏带你快速掌握node.js
Node.js入门
html,css,js 30年了
nodejs环境 09年出现 15年
nodejs为我们解决了2个方面的问题:
- 【锦上添花】让我们前端工程师拥有了后端开发能力(开接口,访问数据库) - 大公司BFF(50+)
- 【✔️】前端工程化(Webpack,vit)
Node.js基本概念
Node.js中文官网
什么是Node.js
作用:
使用 Node.js 编写后端程序 / 支持前端工程化
- 后端程序:提供接口和数据,网页资源等
- 前端工程化:对代码压缩,转译,整合(使用各种工具,提升效率)
Node.js 为何能执行 JS?
首先:浏览器能执行 JS 代码,依靠的是内核中的 V8 引擎(C++ 程序)
其次:Node.js 是基于 Chrome V8 引擎进行封装(运行环境)
区别:都支持 ECMAScript 标准语法,Node.js 有独立的 API
注意:Node.js 环境没有 DOM 和 BOM 等
Node.js 安装
nvm
nvm是一个nodejs版本管理工具,它可以在我们电脑中安装多个node版本,并且可以随意切换版本
nvm官网:nvm文档手册 - nvm是一个nodejs版本管理工具 - nvm中文网
要求:使用nvm安装node 16.19.0(指定版本:为了兼容后期学习的项目)
# ✨安装node 16.19.0版本
nvm install 16.19.0
# ✨查看node版本列表(带*号的表示当前使用的版本)
nvm ls
# ✨切换node版本
nvm use 16.19.0
成功验证:打开 cmd 终端,输入 node -v 命令查看版本号如果有显示,则代表安装成功
使用 Node.js
修改终端默认执行程序
为了防止某些电脑默认使用的是PowerShell执行js报错,我们需要调整一下如下设置为`Command Prompt`
需求:使用nodejs执行一个js文件,使用console.log()打印三个五角星
步骤:
- 新建 index.js 文件,编写打印代码和 for 循环打印 3 个 五角星
- 命令:在 VSCode 集成终端中(ctrl+shift+` 打开),输入 node index.js,回车即可执行,并查看结果
注意:node 文件路径
console.log('Hello, World')
for (let i = 0; i < 3; i++) {
console.log('☆')
}
Node.js 执行目标 JS 文件,需要使用 node index.js 命令来执行(我们可以借助 VSCode 集成终端使用,好处:可以快速切换到目标 JS 文件所在终端目录,利用相对路径找到要执行的目标 JS 文件
准备node项目
在vs code中编写node代码,默认是没有提示的,通过如下步骤创建一个可以有语法提示的node项目,方便接下来的学习。减轻学习负担
- 创建一个空白文件夹 ,例如:mynode
- 使用vs code打开 mynode文件夹
- 按ctrl + shift + `打开终端
- 在终端中输入:
npm install @types/node
后在此项目中编写nodejs代码就有提示了
注意:由于npm的镜像源在国外,需要切到国内才速度快
切换命令:npm set registry=https://repo.huaweicloud.com/repository/npm/
fs模块-读写文件
- 模块:类似插件,封装了方法和属性供我们使用
- fs 模块:是Node.js的内置模块,封装了与本机文件系统进行交互的,方法和属性
- fs 模块使用语法如下:
加载 fs 模块,得到 fs 对象
const fs = require('fs')
写入文件内容语法:
fs.writeFile('文件路径', '写入内容', err => {
// 写入后的回调函数
})
读取文件内容的语法:
fs.readFile('文件路径', (err, data) => {
// 读取后的回调函数
// data 是文件内容的 Buffer 数据流
})
- 需求:向 test.txt 文件写入内容并读取打印
/**
* 目标:使用 fs 模块,读写文件内容
* 语法:
* 1. 引入 fs 模块
* 2. 调用 writeFile 写入内容
* 3. 调用 readFile 读取内容
*/
// 1. 引入 fs 模块
const fs = require('fs')
// 2. 调用 writeFile 写入内容
// 注意:建议写入字符串内容,会覆盖目标文件所有内容
fs.writeFile('./text.txt', '欢迎使用 fs 模块读写文件内容', err => {
if (err) console.log(err)
else console.log('写入成功')
})
// 3. 调用 readFile 读取内容
fs.readFile('./text.txt', (err, data) => {
if (err) console.log(err)
else console.log(data.toString()) // 把 Buffer 数据流转成字符串类型
})
path模块-路径处理
- 为什么在 Node.js 待执行的 JS 代码中要用绝对路径:
Node.js 执行 JS 代码时,代码中的路径都是以终端所在文件夹出发查找相对路径,而不是以我们认为的从代码本身出发,会遇到问题,所以在 Node.js 要执行的代码中,访问其他文件,建议使用绝对路径
- 新建 03 文件夹编写待执行的 JS 代码,访问外层相对路径下的文件,然后在最外层终端路径来执行目标文件,造成问题
- 问题原因:就是从代码文件夹出发,使用
../text.txt
解析路径,找不到目标文件,报错了!
- 解决方案:使用模块内置变量
__dirname
配合 path.join() 来得到绝对路径使用
const fs = require('fs')
console.log(__dirname) // D:\备课代码\2_node_3天\Node_代码\Day01_Node.js入门\代码\03
// 1. 加载 path 模块
const path = require('path')
// 2. 使用 path.join() 来拼接路径
const pathStr = path.join(__dirname, '..', 'text.txt')
console.log(pathStr)
fs.readFile(pathStr, (err, data) => {
if (err) console.log(err)
else console.log(data.toString())
})
- 再次执行查看问题就被修复了!以后在 Node.js 要执行的 JS 代码中访问其他文件的路径,都建议使用绝度路径
案例-压缩前端html
目标:压缩前端代码,让浏览器加载网页更快(体验前端工程化)
前端工程化:对代码压缩,转译,整合,测试,自动部署等等
需求:把public\index.html中 回车符(\r)和换行符(\n)去掉,写入到新 dist\index.html 中
步骤:
- 使用fs.readFile读取public\index.html中的内容
- 正则替换index.html中字符串 /[\r\n]/g
- 将替换后的新内容写入到新dist\index.html中 完成代码压缩
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>时钟案例</title>
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
background-image: linear-gradient(to bottom right, red, gold);
}
.box {
width: 400px;
height: 250px;
background-color: rgba(255, 255, 255, 0.6);
border-radius: 6px;
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
box-shadow: 1px 1px 10px #fff;
text-shadow: 0px 1px 30px white;
display: flex;
justify-content: space-around;
align-items: center;
font-size: 70px;
user-select: none;
padding: 0 20px;
-webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0%, transparent), to(rgba(250, 250, 250, .2)));
}
</style>
</head>
<body>
<div class="box">
<div id="HH">00</div>
<div>:</div>
<div id="mm">00</div>
<div>:</div>
<div id="ss">00</div>
</div>
</body>
</html>
/*
职责:将 public/index.html压缩
代码:
1.使用fs.readFile读取public\index.html中的内容
2.正则替换index.html中字符串/rn]/g
3.将替换后的新内容写入到新dist\index.html中完成代码压缩
*/
const { readFile,writeFile } = require("fs");
const path = require("path");
// 1. 读取未压缩的index.html内容
let indexPath = path.join(__dirname, 'public/index.html')
readFile(indexPath, (err, data) => {
if (err) {
console.log(err);
} else {
// console.log(data.toString())
let unzipHtml = data.toString()
// 2.正则替换index.html中字符串/rn]/g
const reg = /[\r\n]/g
const zipHtml = unzipHtml.replace(reg, '')
// console.log(zipHtml)
// 3.将替换后的新内容写入到新dist\index.html中完成代码压缩
let targetPath = path.join(__dirname, 'dist/index.html')
writeFile(targetPath,zipHtml,(err)=>{
if(err){
console.log(err);
}else{
console.log('写入成功');
}
})
}
})
案例-压缩前端JS
需求:把准备好的 JS 文件代码的回车符,换行符,打印语句去掉,并插入到之前 html 内容之后
步骤:
- 读取 public/index.js 内容
- 使用正则替换内容字符串里的\r \n 和console.log('xxx')
-
- /[\r\n]/g
- /console.log\('.+?'\);/g
- 拼接 html 内容写入到 dist/index.html 内
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>时钟案例</title>
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
background-image: linear-gradient(to bottom right, red, gold);
}
.box {
width: 400px;
height: 250px;
background-color: rgba(255, 255, 255, 0.6);
border-radius: 6px;
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
box-shadow: 1px 1px 10px #fff;
text-shadow: 0px 1px 30px white;
display: flex;
justify-content: space-around;
align-items: center;
font-size: 70px;
user-select: none;
padding: 0 20px;
-webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0%, transparent), to(rgba(250, 250, 250, .2)));
}
</style>
</head>
<body>
<div class="box">
<div id="HH">00</div>
<div>:</div>
<div id="mm">00</div>
<div>:</div>
<div id="ss">00</div>
</div>
</body>
</html>
window.addEventListener('load', function () {
console.log('测试-网页加载完成了');
clock();
setInterval(clock, 1000);
});
function clock() {
console.log('测试-时钟函数调用了');
let dt = new Date();
let HH = dt.getHours();
let mm = dt.getMinutes();
let ss = dt.getSeconds();
console.log(dt, HH, mm, ss);
document.querySelector('#HH').innerHTML = padZero(HH);
document.querySelector('#mm').innerHTML = padZero(mm);
document.querySelector('#ss').innerHTML = padZero(ss);
};
function padZero(n) {
console.log('时间测试');
return n > 9 ? n : '0' + n;
}
/**
* 目标二:压缩 js 里代码,并整合到 html 中一起运行
* 2.1 读取 public/index.js 内容
* 2.2 使用正则替换内容字符串里的,回车符\r 换行符\n 打印语句console.log('xxx');
* 2.3 确认后,拼接 html 内容写入到 dist/index.html 内
*/
const fs = require('fs')
const path = require('path')
fs.readFile(path.join(__dirname, 'public', 'index.html'), (err, data) => {
const htmlStr = data.toString()
const resultStr = htmlStr.replace(/[\r\n]/g, '')
// 2.1 读取 public/index.js 内容
fs.readFile(path.join(__dirname, 'public', 'index.js'), (err, data) => {
const jsStr = data.toString()
// 2.2 使用正则替换内容字符串里的,回车符\r 换行符\n 打印语句console.log('xxx');
const jsResultStr = jsStr.replace(/[\r\n]/g, '').replace(/console.log\('.+?'\);/g, '')
const result = `<script>${jsResultStr}</script>`
console.log(result)
// 2.3 确认后,拼接 html 内容写入到 dist/index.html 内
fs.writeFile(path.join(__dirname, 'dist', 'index.html'), resultStr + result, err => {
if (err) console.log(err)
else console.log('压缩成功')
})
})
})
http模块-创建Web服务
什么是Web服务?
Web 服务:是一种通过网络进行通信和交换数据的技术
- 大白话:一个程序,用来提供网上信息浏览功能
我们前端可以使用 Node.js来构建一个 Web 服务来与客户端进行数据交换
【前置知识】端口号
vision
http://8.138.119.204:80
创建3000端口的Web服务
基于 Node.js 环境,使用内置 http 模块,创建 Web 服务程序
需求:引入 http 模块,使用相关语法,创建 Web 服务程序,响应返回给请求方一句提示 ‘hello,world’
步骤:
- 引入 http 模块,创建 Web 服务对象
- 监听 request 请求事件,对本次请求,做一些响应处理
- 启动 Web 服务监听对应端口号
- 运行本服务在终端进程中,用浏览器发起请求 http://localhost:3000/
注意:
- 本机的域名叫做 localhost 或者 127.0.0.1
- 一个端口只能有一个服务监听,如果前一个服务器未关闭,则第二次启动会报错
/**
* 目标:使用 http 模块,创建 Web 服务
* Web服务:一个程序,用于提供网上信息浏览服务
* 步骤:
* 1. 引入 http 模块,创建 Web 服务对象
* 2. 监听 request 事件,对本次请求,做一些响应处理
* 3. 启动 Web 服务监听对应端口号
* 4. 运行本服务在终端,用浏览器访问 http://localhost:3000/ 发起请求(localhost 是本机域名)
* 注意:终端里启动了服务,如果想要终止按 ctrl c 停止即可
*/
// 1. 引入 http 模块,创建 Web 服务对象
const http = require('http')
const server = http.createServer()
// 2. 监听 request 事件,对本次请求,做一些响应处理
server.on('request', (req, res) => {
res.end('hello, world') // 一次请求只能对应一次响应
})
// 3. 启动 Web 服务监听对应端口号
server.listen(3000, () => {
console.log('Web 服务启动了')
})
Web服务-支持中文字符
让 Web 服务,返回中文字符,浏览器正确解析加载
步骤:给 Web 服务程序添加响应头,设置内容类型和正确的编码格式,重启 Web 服务测试访问即可
res.setHeader('Content-Type', 'text/html;charset=utf-8')
- 编码:编码是信息从一种形式或格式转换为另一种形式的过程,指的把文字在计算机里的二进制数据,用什么形式展示出来
案例-省份列表接口
- 需求:基于 Web 服务,开发提供省份列表数据的接口,了解下后端的代码工作过程
- 步骤:
-
- 基于 http 模块,创建 Web 服务
-
- 使用 req.url 获取请求资源路径,并读取 province.json 理论省份数据返回给请求方
-
- 其他路径,暂时返回不存在的提示
-
- 运行 Web 服务,用浏览器发起请求测试,看是否可以获取到省份列表数据
- 代码如下:
[
"北京",
"天津",
"河北省",
"山西省",
"内蒙古自治区",
"辽宁省",
"吉林省",
"黑龙江省",
"上海",
"江苏省",
"浙江省",
"安徽省",
"福建省",
"江西省",
"山东省",
"河南省",
"湖北省",
"湖南省",
"广东省",
"广西壮族自治区",
"海南省",
"重庆",
"四川省",
"贵州省",
"云南省",
"西藏自治区",
"陕西省",
"甘肃省",
"青海省",
"宁夏回族自治区",
"新疆维吾尔自治区",
"台湾",
"香港特别行政区",
"澳门特别行政区"
]
/*
这个web服务提供的服务有:
1. 当浏览器或者axios发送了 http://localhost:3000/api/province请求,就响应省份的json数据给客户端
拆解流程:
1. 准备一个json文件
2. 准备一个web服务(http)
3. request事件里面做出响应
-> fs.readFile读取准备的json文件数据
-> 设置响应头Content-Type
-> res.end()响应
*/
const { readFile } = require('fs')
const http = require('http')
const path = require('path')
const server = http.createServer()
server.on('request', (req, res) => {
// 1. 如何判断客户端请求上来的路径地址是什么?
// req.url存储的是请求的url的路径+参数
// console.log(req.url)
if (req.url == '/api/province') {
// 2. 读取json文件内容响应
readFile(path.join(__dirname,'/data/province.json'),(err,data)=>{
if(err){
res.end('接口500')
}else{
let jsonStr = data.toString()
res.setHeader('Content-Type','application/json')
res.end(jsonStr)
}
})
}else{
res.end('资源没有找到404')
}
})
server.listen(3000, () => {
console.log('web服务已经启动,请使用http://localhost:3000来访问');
})
案例-城市列表接口
- 需求:基于刚刚的 Web 服务,开发提供城市列表数据的接口,了解下后端代码的工作过程
前置知识:字符串.startsWith() 和querystring模块
- 步骤:
-
- 判断 req.url 资源路径+查询字符串,路径前缀匹配 /api/city
-
- 借助 querystring 模块的方法,格式化查询字符串
-
- 读取 city.json 城市数据,匹配省份名字下属城市列表
-
- 返回城市列表,启动 Web 服务测试
- 代码如下:
{
"北京": ["北京市"],
"天津": ["天津市"],
"河北省": [
"石家庄市",
"唐山市",
"秦皇岛市",
"邯郸市",
"邢台市",
"保定市",
"张家口市",
"承德市",
"沧州市",
"廊坊市",
"衡水市"
],
"山西省": [
"太原市",
"大同市",
"阳泉市",
"长治市",
"晋城市",
"朔州市",
"晋中市",
"运城市",
"忻州市",
"临汾市",
"吕梁市"
],
"内蒙古自治区": [
"呼和浩特市",
"包头市",
"乌海市",
"赤峰市",
"通辽市",
"鄂尔多斯市",
"呼伦贝尔市",
"巴彦淖尔市",
"乌兰察布市",
"兴安盟",
"锡林郭勒盟",
"阿拉善盟"
],
"辽宁省": [
"沈阳市",
"大连市",
"鞍山市",
"抚顺市",
"本溪市",
"丹东市",
"锦州市",
"营口市",
"阜新市",
"辽阳市",
"盘锦市",
"铁岭市",
"朝阳市",
"葫芦岛市"
],
"吉林省": [
"长春市",
"吉林市",
"四平市",
"辽源市",
"通化市",
"白山市",
"松原市",
"白城市",
"延边朝鲜族自治州"
],
"黑龙江省": [
"哈尔滨市",
"齐齐哈尔市",
"鸡西市",
"鹤岗市",
"双鸭山市",
"大庆市",
"伊春市",
"佳木斯市",
"七台河市",
"牡丹江市",
"黑河市",
"绥化市",
"大兴安岭地区"
],
"上海": ["上海市"],
"江苏省": [
"南京市",
"无锡市",
"徐州市",
"常州市",
"苏州市",
"南通市",
"连云港市",
"淮安市",
"盐城市",
"扬州市",
"镇江市",
"泰州市",
"宿迁市"
],
"浙江省": [
"杭州市",
"宁波市",
"温州市",
"嘉兴市",
"湖州市",
"绍兴市",
"金华市",
"衢州市",
"舟山市",
"台州市",
"丽水市"
],
"安徽省": [
"合肥市",
"芜湖市",
"蚌埠市",
"淮南市",
"马鞍山市",
"淮北市",
"铜陵市",
"安庆市",
"黄山市",
"滁州市",
"阜阳市",
"宿州市",
"巢湖市",
"六安市",
"亳州市",
"池州市",
"宣城市"
],
"福建省": [
"福州市",
"厦门市",
"莆田市",
"三明市",
"泉州市",
"漳州市",
"南平市",
"龙岩市",
"宁德市"
],
"江西省": [
"南昌市",
"景德镇市",
"萍乡市",
"九江市",
"新余市",
"鹰潭市",
"赣州市",
"吉安市",
"宜春市",
"抚州市",
"上饶市"
],
"山东省": [
"济南市",
"青岛市",
"淄博市",
"枣庄市",
"东营市",
"烟台市",
"潍坊市",
"济宁市",
"泰安市",
"威海市",
"日照市",
"莱芜市",
"临沂市",
"德州市",
"聊城市",
"滨州市",
"菏泽市"
],
"河南省": [
"郑州市",
"开封市",
"洛阳市",
"平顶山市",
"安阳市",
"鹤壁市",
"新乡市",
"焦作市",
"濮阳市",
"许昌市",
"漯河市",
"三门峡市",
"南阳市",
"商丘市",
"信阳市",
"周口市",
"驻马店市"
],
"湖北省": [
"武汉市",
"黄石市",
"十堰市",
"宜昌市",
"襄阳市",
"鄂州市",
"荆门市",
"孝感市",
"荆州市",
"黄冈市",
"咸宁市",
"随州市",
"恩施土家族苗族自治州"
],
"湖南省": [
"长沙市",
"株洲市",
"湘潭市",
"衡阳市",
"邵阳市",
"岳阳市",
"常德市",
"张家界市",
"益阳市",
"郴州市",
"永州市",
"怀化市",
"娄底市",
"湘西土家族苗族自治州"
],
"广东省": [
"广州市",
"韶关市",
"深圳市",
"珠海市",
"汕头市",
"佛山市",
"江门市",
"湛江市",
"茂名市",
"肇庆市",
"惠州市",
"梅州市",
"汕尾市",
"河源市",
"阳江市",
"清远市",
"东莞市",
"中山市",
"潮州市",
"揭阳市",
"云浮市"
],
"广西壮族自治区": [
"南宁市",
"柳州市",
"桂林市",
"梧州市",
"北海市",
"防城港市",
"钦州市",
"贵港市",
"玉林市",
"百色市",
"贺州市",
"河池市",
"来宾市",
"崇左市"
],
"海南省": ["海口市", "三亚市", "三沙市"],
"重庆": ["重庆市"],
"四川省": [
"成都市",
"自贡市",
"攀枝花市",
"泸州市",
"德阳市",
"绵阳市",
"广元市",
"遂宁市",
"内江市",
"乐山市",
"南充市",
"眉山市",
"宜宾市",
"广安市",
"达州市",
"雅安市",
"巴中市",
"资阳市",
"阿坝藏族羌族自治州",
"甘孜藏族自治州",
"凉山彝族自治州"
],
"贵州省": [
"贵阳市",
"六盘水市",
"遵义市",
"安顺市",
"铜仁市",
"黔西南布依族苗族自治州",
"毕节市",
"黔东南苗族侗族自治州",
"黔南布依族苗族自治州"
],
"云南省": [
"昆明市",
"曲靖市",
"玉溪市",
"保山市",
"昭通市",
"丽江市",
"普洱市",
"临沧市",
"楚雄彝族自治州",
"红河哈尼族彝族自治州",
"文山壮族苗族自治州",
"西双版纳傣族自治州",
"大理白族自治州",
"德宏傣族景颇族自治州",
"怒江傈僳族自治州",
"迪庆藏族自治州"
],
"西藏自治区": [
"拉萨市",
"昌都地区",
"山南地区",
"日喀则地区",
"那曲地区",
"阿里地区",
"林芝地区"
],
"陕西省": [
"西安市",
"铜川市",
"宝鸡市",
"咸阳市",
"渭南市",
"延安市",
"汉中市",
"榆林市",
"安康市",
"商洛市"
],
"甘肃省": [
"兰州市",
"嘉峪关市",
"金昌市",
"白银市",
"天水市",
"武威市",
"张掖市",
"平凉市",
"酒泉市",
"庆阳市",
"定西市",
"陇南市",
"临夏回族自治州",
"甘南藏族自治州"
],
"青海省": [
"西宁市",
"海东市",
"海北藏族自治州",
"黄南藏族自治州",
"海南藏族自治州",
"果洛藏族自治州",
"玉树藏族自治州",
"海西蒙古族藏族自治州"
],
"宁夏回族自治区": ["银川市", "石嘴山市", "吴忠市", "固原市", "中卫市"],
"新疆维吾尔自治区": [
"乌鲁木齐市",
"克拉玛依市",
"吐鲁番地区",
"哈密地区",
"昌吉回族自治州",
"博尔塔拉蒙古自治州",
"巴音郭楞蒙古自治州",
"阿克苏地区",
"克孜勒苏柯尔克孜自治州",
"喀什地区",
"和田地区",
"伊犁哈萨克自治州",
"塔城地区",
"阿勒泰地区"
],
"台湾省": [
"台北市",
"高雄市",
"台南市",
"台中市",
"金门县",
"南投县",
"基隆市",
"新竹市",
"嘉义市",
"新北市",
"宜兰县",
"新竹县",
"桃园县",
"苗栗县",
"彰化县",
"嘉义县",
"云林县",
"屏东县",
"台东县",
"花莲县",
"澎湖县",
"连江县"
],
"香港特别行政区": ["香港岛", "九龙", "新界"],
"澳门特别行政区": ["澳门半岛", "离岛"]
}
/*
这个web服务提供的服务有:
1. 当浏览器或者axios发送了 http://localhost:3000/api/province请求,就响应省份的json数据给客户端
拆解流程:
1. 准备一个json文件
2. 准备一个web服务(http)
3. request事件里面做出响应
-> fs.readFile读取准备的json文件数据
-> 设置响应头Content-Type
-> res.end()响应
*/
const { readFile } = require('fs')
const http = require('http')
const path = require('path')
const qs = require('querystring')
const server = http.createServer()
server.on('request', (req, res) => {
// 1. 如何判断客户端请求上来的路径地址是什么?
// req.url存储的是请求的url的路径+参数
// console.log(req.url)
if (req.url == '/api/province') {
// 2. 读取json文件内容响应
readFile(path.join(__dirname, '/data/province.json'), (err, data) => {
if (err) {
res.end('接口500')
} else {
let jsonStr = data.toString()
res.setHeader('Content-Type', 'application/json')
res.end(jsonStr)
}
})
}
else if (req.url.startsWith('/api/city')) {
// 城市数据的提供
// 1. 获取请求pname的值
// req.url // /api/city?pname=辽宁省
let queryString = req.url.split('?')[1] //pname=辽宁省
const queryObj = qs.parse(queryString) // {pname:'辽宁省'}
// console.log(queryObj.pname);
// 2. 根据pname的值从city.json中获取指定的省份的城市响应
readFile(path.join(__dirname, 'data/city.json'), (err, data) => {
if (err) {
res.end('500 server error')
} else {
// 字符串
const cityJsonString = data.toString()
// 必须将cityJsonString 转换js对象
const cityObj = JSON.parse(cityJsonString)
let cityArr = cityObj[queryObj.pname] // ['广州市','深圳市','''']
res.setHeader('Content-Type', 'application/json;')
res.end(JSON.stringify(cityArr))
}
})
}
else {
res.end('资源没有找到404')
}
})
server.listen(3000, () => {
console.log('web服务已经启动,请使用http://localhost:3000来访问');
})
案例-浏览时钟
- 需求:基于 Web 服务,开发提供网页资源的功能,了解下后端的代码工作过程
- 步骤:
-
- 基于 http 模块,创建 Web 服务
-
- 使用 req.url 获取请求资源路径为 /index.html 的时候,读取 index.html 文件内容字符串返回给请求方
-
- 其他路径,暂时返回不存在的提示
-
- 运行 Web 服务,用浏览器发起http://localhost:3000/index.html请求查看结果是否为倒计时页面
- 代码如下:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>时钟案例</title> <style> html, body { margin: 0; padding: 0; height: 100%; background-image: linear-gradient(to bottom right, red, gold); } .box { width: 400px; height: 250px; background-color: rgba(255, 255, 255, 0.6); border-radius: 6px; position: absolute; left: 50%; top: 40%; transform: translate(-50%, -50%); box-shadow: 1px 1px 10px #fff; text-shadow: 0px 1px 30px white; display: flex; justify-content: space-around; align-items: center; font-size: 70px; user-select: none; padding: 0 20px; -webkit-box-reflect: below 0px -webkit-gradient(linear, left top, left bottom, from(transparent), color-stop(0%, transparent), to(rgba(250, 250, 250, .2))); } </style></head><body> <div class="box"> <div id="HH">00</div> <div>:</div> <div id="mm">00</div> <div>:</div> <div id="ss">00</div> </div></body></html><script>window.addEventListener('load', function () { clock(); setInterval(clock, 1000);});function clock() { let dt = new Date(); let HH = dt.getHours(); let mm = dt.getMinutes(); let ss = dt.getSeconds(); console.log(dt, HH, mm, ss); document.querySelector('#HH').innerHTML = padZero(HH); document.querySelector('#mm').innerHTML = padZero(mm); document.querySelector('#ss').innerHTML = padZero(ss);};function padZero(n) { return n > 9 ? n : '0' + n;}</script>
/**
* 目标:编写 web 服务,监听请求的是 /index.html 路径的时候,返回 dist/index.html 时钟案例页面内容
* 步骤:
* 1. 基于 http 模块,创建 Web 服务
* 2. 使用 req.url 获取请求资源路径,并读取 index.html 里字符串内容返回给请求方
* 3. 其他路径,暂时返回不存在提示
* 4. 运行 Web 服务,用浏览器发起请求
*/
const fs = require('fs')
const path = require('path')
// 1. 基于 http 模块,创建 Web 服务
const http = require('http')
const server = http.createServer()
server.on('request', (req, res) => {
// 2. 使用 req.url 获取请求资源路径,并读取 index.html 里字符串内容返回给请求方
if (req.url === '/index.html') {
fs.readFile(path.join(__dirname, 'dist/index.html'), (err, data) => {
res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.end(data.toString())
})
} else {
// 3. 其他路径,暂时返回不存在提示
res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.end('你要访问的资源路径不存在')
}
})
server.listen(8080, () => {
console.log('Web 服务启动了')
})