Node.js入门html,css,js 30年了nodejs环境 09年出现 15年

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()打印三个五角星

步骤:

  1. 新建 index.js 文件,编写打印代码和 for 循环打印 3 个 五角星
  2. 命令:在 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项目,方便接下来的学习。减轻学习负担

  1. 创建一个空白文件夹 ,例如:mynode
  2. 使用vs code打开 mynode文件夹
  3. 按ctrl + shift + `打开终端
  4. 在终端中输入:npm install @types/node 后在此项目中编写nodejs代码就有提示了

注意:由于npm的镜像源在国外,需要切到国内才速度快

切换命令:npm set registry=https://repo.huaweicloud.com/repository/npm/

fs模块-读写文件

  1. 模块:类似插件,封装了方法和属性供我们使用
  1. fs 模块:是Node.js的内置模块,封装了与本机文件系统进行交互的,方法和属性
  1. fs 模块使用语法如下:

加载 fs 模块,得到 fs 对象

复制代码
const fs = require('fs')

写入文件内容语法:

复制代码
fs.writeFile('文件路径', '写入内容', err => {
  // 写入后的回调函数
})

读取文件内容的语法:

复制代码
fs.readFile('文件路径', (err, data) => {
  // 读取后的回调函数
  // data 是文件内容的 Buffer 数据流
})
  1. 需求:向 test.txt 文件写入内容并读取打印

    /**

    • 目标:使用 fs 模块,读写文件内容
    • 语法:
      1. 引入 fs 模块
      1. 调用 writeFile 写入内容
      1. 调用 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模块-路径处理

  1. 为什么在 Node.js 待执行的 JS 代码中要用绝对路径:

Node.js 执行 JS 代码时,代码中的路径都是以终端所在文件夹出发查找相对路径,而不是以我们认为的从代码本身出发,会遇到问题,所以在 Node.js 要执行的代码中,访问其他文件,建议使用绝对路径

  1. 新建 03 文件夹编写待执行的 JS 代码,访问外层相对路径下的文件,然后在最外层终端路径来执行目标文件,造成问题

  2. 问题原因:就是从代码文件夹出发,使用../text.txt解析路径,找不到目标文件,报错了!

  1. 解决方案:使用模块内置变量 __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())
    })

  2. 再次执行查看问题就被修复了!以后在 Node.js 要执行的 JS 代码中访问其他文件的路径,都建议使用绝度路径

案例-压缩前端html

目标:压缩前端代码,让浏览器加载网页更快(体验前端工程化)

前端工程化:对代码压缩,转译,整合,测试,自动部署等等

需求:把public\index.html中 回车符(\r)和换行符(\n)去掉,写入到新 dist\index.html 中

步骤:

  1. 使用fs.readFile读取public\index.html中的内容

  2. 正则替换index.html中字符串 /[\r\n]/g

  3. 将替换后的新内容写入到新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>
    00
    :
    00
    :
    00
    </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 内容之后

步骤:

  1. 读取 public/index.js 内容
  2. 使用正则替换内容字符串里的\r \n 和console.log('xxx')
    1. /[\r\n]/g
    2. /console.log\('.+?'\);/g
  1. 拼接 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>
    00
    :
    00
    :
    00
    </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'

步骤:

  1. 引入 http 模块,创建 Web 服务对象
  2. 监听 request 请求事件,对本次请求,做一些响应处理
  3. 启动 Web 服务监听对应端口号
  4. 运行本服务在终端进程中,用浏览器发起请求 http://localhost:3000/

注意:

  1. 本机的域名叫做 localhost 或者 127.0.0.1

  2. 一个端口只能有一个服务监听,如果前一个服务器未关闭,则第二次启动会报错

    /**

    • 目标:使用 http 模块,创建 Web 服务
    • Web服务:一个程序,用于提供网上信息浏览服务
    • 步骤:
      1. 引入 http 模块,创建 Web 服务对象
      1. 监听 request 事件,对本次请求,做一些响应处理
      1. 启动 Web 服务监听对应端口号
      1. 运行本服务在终端,用浏览器访问 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')
  1. 编码:编码是信息从一种形式或格式转换为另一种形式的过程,指的把文字在计算机里的二进制数据,用什么形式展示出来

案例-省份列表接口

  1. 需求:基于 Web 服务,开发提供省份列表数据的接口,了解下后端的代码工作过程
  1. 步骤:
    1. 基于 http 模块,创建 Web 服务
    1. 使用 req.url 获取请求资源路径,并读取 province.json 理论省份数据返回给请求方
    1. 其他路径,暂时返回不存在的提示
    1. 运行 Web 服务,用浏览器发起请求测试,看是否可以获取到省份列表数据
  1. 代码如下:

    [
    "北京",
    "天津",
    "河北省",
    "山西省",
    "内蒙古自治区",
    "辽宁省",
    "吉林省",
    "黑龙江省",
    "上海",
    "江苏省",
    "浙江省",
    "安徽省",
    "福建省",
    "江西省",
    "山东省",
    "河南省",
    "湖北省",
    "湖南省",
    "广东省",
    "广西壮族自治区",
    "海南省",
    "重庆",
    "四川省",
    "贵州省",
    "云南省",
    "西藏自治区",
    "陕西省",
    "甘肃省",
    "青海省",
    "宁夏回族自治区",
    "新疆维吾尔自治区",
    "台湾",
    "香港特别行政区",
    "澳门特别行政区"
    ]

    /*
    这个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来访问');
    })

案例-城市列表接口

  1. 需求:基于刚刚的 Web 服务,开发提供城市列表数据的接口,了解下后端代码的工作过程

前置知识:字符串.startsWith() 和querystring模块

  1. 步骤:
    1. 判断 req.url 资源路径+查询字符串,路径前缀匹配 /api/city
    1. 借助 querystring 模块的方法,格式化查询字符串
    1. 读取 city.json 城市数据,匹配省份名字下属城市列表
    1. 返回城市列表,启动 Web 服务测试
  1. 代码如下:

    {
    "北京": ["北京市"],
    "天津": ["天津市"],
    "河北省": [
    "石家庄市",
    "唐山市",
    "秦皇岛市",
    "邯郸市",
    "邢台市",
    "保定市",
    "张家口市",
    "承德市",
    "沧州市",
    "廊坊市",
    "衡水市"
    ],
    "山西省": [
    "太原市",
    "大同市",
    "阳泉市",
    "长治市",
    "晋城市",
    "朔州市",
    "晋中市",
    "运城市",
    "忻州市",
    "临汾市",
    "吕梁市"
    ],
    "内蒙古自治区": [
    "呼和浩特市",
    "包头市",
    "乌海市",
    "赤峰市",
    "通辽市",
    "鄂尔多斯市",
    "呼伦贝尔市",
    "巴彦淖尔市",
    "乌兰察布市",
    "兴安盟",
    "锡林郭勒盟",
    "阿拉善盟"
    ],
    "辽宁省": [
    "沈阳市",
    "大连市",
    "鞍山市",
    "抚顺市",
    "本溪市",
    "丹东市",
    "锦州市",
    "营口市",
    "阜新市",
    "辽阳市",
    "盘锦市",
    "铁岭市",
    "朝阳市",
    "葫芦岛市"
    ],
    "吉林省": [
    "长春市",
    "吉林市",
    "四平市",
    "辽源市",
    "通化市",
    "白山市",
    "松原市",
    "白城市",
    "延边朝鲜族自治州"
    ],
    "黑龙江省": [
    "哈尔滨市",
    "齐齐哈尔市",
    "鸡西市",
    "鹤岗市",
    "双鸭山市",
    "大庆市",
    "伊春市",
    "佳木斯市",
    "七台河市",
    "牡丹江市",
    "黑河市",
    "绥化市",
    "大兴安岭地区"
    ],
    "上海": ["上海市"],
    "江苏省": [
    "南京市",
    "无锡市",
    "徐州市",
    "常州市",
    "苏州市",
    "南通市",
    "连云港市",
    "淮安市",
    "盐城市",
    "扬州市",
    "镇江市",
    "泰州市",
    "宿迁市"
    ],
    "浙江省": [
    "杭州市",
    "宁波市",
    "温州市",
    "嘉兴市",
    "湖州市",
    "绍兴市",
    "金华市",
    "衢州市",
    "舟山市",
    "台州市",
    "丽水市"
    ],
    "安徽省": [
    "合肥市",
    "芜湖市",
    "蚌埠市",
    "淮南市",
    "马鞍山市",
    "淮北市",
    "铜陵市",
    "安庆市",
    "黄山市",
    "滁州市",
    "阜阳市",
    "宿州市",
    "巢湖市",
    "六安市",
    "亳州市",
    "池州市",
    "宣城市"
    ],
    "福建省": [
    "福州市",
    "厦门市",
    "莆田市",
    "三明市",
    "泉州市",
    "漳州市",
    "南平市",
    "龙岩市",
    "宁德市"
    ],
    "江西省": [
    "南昌市",
    "景德镇市",
    "萍乡市",
    "九江市",
    "新余市",
    "鹰潭市",
    "赣州市",
    "吉安市",
    "宜春市",
    "抚州市",
    "上饶市"
    ],
    "山东省": [
    "济南市",
    "青岛市",
    "淄博市",
    "枣庄市",
    "东营市",
    "烟台市",
    "潍坊市",
    "济宁市",
    "泰安市",
    "威海市",
    "日照市",
    "莱芜市",
    "临沂市",
    "德州市",
    "聊城市",
    "滨州市",
    "菏泽市"
    ],
    "河南省": [
    "郑州市",
    "开封市",
    "洛阳市",
    "平顶山市",
    "安阳市",
    "鹤壁市",
    "新乡市",
    "焦作市",
    "濮阳市",
    "许昌市",
    "漯河市",
    "三门峡市",
    "南阳市",
    "商丘市",
    "信阳市",
    "周口市",
    "驻马店市"
    ],
    "湖北省": [
    "武汉市",
    "黄石市",
    "十堰市",
    "宜昌市",
    "襄阳市",
    "鄂州市",
    "荆门市",
    "孝感市",
    "荆州市",
    "黄冈市",
    "咸宁市",
    "随州市",
    "恩施土家族苗族自治州"
    ],
    "湖南省": [
    "长沙市",
    "株洲市",
    "湘潭市",
    "衡阳市",
    "邵阳市",
    "岳阳市",
    "常德市",
    "张家界市",
    "益阳市",
    "郴州市",
    "永州市",
    "怀化市",
    "娄底市",
    "湘西土家族苗族自治州"
    ],
    "广东省": [
    "广州市",
    "韶关市",
    "深圳市",
    "珠海市",
    "汕头市",
    "佛山市",
    "江门市",
    "湛江市",
    "茂名市",
    "肇庆市",
    "惠州市",
    "梅州市",
    "汕尾市",
    "河源市",
    "阳江市",
    "清远市",
    "东莞市",
    "中山市",
    "潮州市",
    "揭阳市",
    "云浮市"
    ],
    "广西壮族自治区": [
    "南宁市",
    "柳州市",
    "桂林市",
    "梧州市",
    "北海市",
    "防城港市",
    "钦州市",
    "贵港市",
    "玉林市",
    "百色市",
    "贺州市",
    "河池市",
    "来宾市",
    "崇左市"
    ],
    "海南省": ["海口市", "三亚市", "三沙市"],
    "重庆": ["重庆市"],
    "四川省": [
    "成都市",
    "自贡市",
    "攀枝花市",
    "泸州市",
    "德阳市",
    "绵阳市",
    "广元市",
    "遂宁市",
    "内江市",
    "乐山市",
    "南充市",
    "眉山市",
    "宜宾市",
    "广安市",
    "达州市",
    "雅安市",
    "巴中市",
    "资阳市",
    "阿坝藏族羌族自治州",
    "甘孜藏族自治州",
    "凉山彝族自治州"
    ],
    "贵州省": [
    "贵阳市",
    "六盘水市",
    "遵义市",
    "安顺市",
    "铜仁市",
    "黔西南布依族苗族自治州",
    "毕节市",
    "黔东南苗族侗族自治州",
    "黔南布依族苗族自治州"
    ],
    "云南省": [
    "昆明市",
    "曲靖市",
    "玉溪市",
    "保山市",
    "昭通市",
    "丽江市",
    "普洱市",
    "临沧市",
    "楚雄彝族自治州",
    "红河哈尼族彝族自治州",
    "文山壮族苗族自治州",
    "西双版纳傣族自治州",
    "大理白族自治州",
    "德宏傣族景颇族自治州",
    "怒江傈僳族自治州",
    "迪庆藏族自治州"
    ],
    "西藏自治区": [
    "拉萨市",
    "昌都地区",
    "山南地区",
    "日喀则地区",
    "那曲地区",
    "阿里地区",
    "林芝地区"
    ],
    "陕西省": [
    "西安市",
    "铜川市",
    "宝鸡市",
    "咸阳市",
    "渭南市",
    "延安市",
    "汉中市",
    "榆林市",
    "安康市",
    "商洛市"
    ],
    "甘肃省": [
    "兰州市",
    "嘉峪关市",
    "金昌市",
    "白银市",
    "天水市",
    "武威市",
    "张掖市",
    "平凉市",
    "酒泉市",
    "庆阳市",
    "定西市",
    "陇南市",
    "临夏回族自治州",
    "甘南藏族自治州"
    ],
    "青海省": [
    "西宁市",
    "海东市",
    "海北藏族自治州",
    "黄南藏族自治州",
    "海南藏族自治州",
    "果洛藏族自治州",
    "玉树藏族自治州",
    "海西蒙古族藏族自治州"
    ],
    "宁夏回族自治区": ["银川市", "石嘴山市", "吴忠市", "固原市", "中卫市"],
    "新疆维吾尔自治区": [
    "乌鲁木齐市",
    "克拉玛依市",
    "吐鲁番地区",
    "哈密地区",
    "昌吉回族自治州",
    "博尔塔拉蒙古自治州",
    "巴音郭楞蒙古自治州",
    "阿克苏地区",
    "克孜勒苏柯尔克孜自治州",
    "喀什地区",
    "和田地区",
    "伊犁哈萨克自治州",
    "塔城地区",
    "阿勒泰地区"
    ],
    "台湾省": [
    "台北市",
    "高雄市",
    "台南市",
    "台中市",
    "金门县",
    "南投县",
    "基隆市",
    "新竹市",
    "嘉义市",
    "新北市",
    "宜兰县",
    "新竹县",
    "桃园县",
    "苗栗县",
    "彰化县",
    "嘉义县",
    "云林县",
    "屏东县",
    "台东县",
    "花莲县",
    "澎湖县",
    "连江县"
    ],
    "香港特别行政区": ["香港岛", "九龙", "新界"],
    "澳门特别行政区": ["澳门半岛", "离岛"]
    }

    /*
    这个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来访问');
    })

案例-浏览时钟

  1. 需求:基于 Web 服务,开发提供网页资源的功能,了解下后端的代码工作过程
  1. 步骤:
    1. 基于 http 模块,创建 Web 服务
    1. 使用 req.url 获取请求资源路径为 /index.html 的时候,读取 index.html 文件内容字符串返回给请求方
    1. 其他路径,暂时返回不存在的提示
    1. 运行 Web 服务,用浏览器发起http://localhost:3000/index.html请求查看结果是否为倒计时页面
  1. 代码如下:

    <!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>
    00
    :
    00
    :
    00
    </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 服务
      1. 使用 req.url 获取请求资源路径,并读取 index.html 里字符串内容返回给请求方
      1. 其他路径,暂时返回不存在提示
      1. 运行 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 服务启动了')
        })

今日作业(必完成)

tlias上发布

知识回顾

  1. node基本概念
    1. node是什么?-> node是一个执行js的环境
    2. node和浏览器有和相同点以及区别?
      1. 相同点:① node和浏览器都支持ECMAScript的标准语法 ② 都是V8引擎来解析js的
      2. 不同点:① node不支持DOM和BOM操作的 ② node本身提供的fs,path,http,request等这些模块浏览器是没有的
    1. node给前端做了哪些赋能?
      1. 可以让前端工程师做后端接口的开发(可以操作数据库,并且可以开启服务器 -> Web服务)
      2. 工程化(将来可以开发大型项目,让代码有良好的组织结构,维护很方便)
  1. 如何安装和配置node环境(提示)
    1. nvm来管理多个node版本之间的切换的
    2. 直接下载node安装包,双击安装
    3. 在开发目录中执行npm install @types/node 就能具备node环境的提示功能
  1. 内置模块
    1. 引入一个node模块使用的关键字 require()
    2. fs -> 读写文件
      1. fs.readFile (异步方法)
      2. fs.writeFile (异步方法)
    1. path -> join()方法主要是用来拼接绝对路径
      1. __dirname -> 获取当前js文件所在的绝对路径
  1. http模块
    1. 基本网络知识
      1. 域名(IP)
      2. 端口
        1. 作用:是操作系统用来对外通讯的,需要我们编写web服务来监听这个端口,从而实现对外通讯
        2. 范围: 0 - 65535 ,总端口是是65536个
      1. 资源路径
      2. 查询参数
      3. http协议
        1. http请求协议 (约束客户端通过什么数据格式向服务器发送数据)
          1. 请求行
          2. 请求头
          3. 空白行
          4. 请求体
        1. http响应协议(约束服务器向客户端发送什么数据)
          1. 响应行
          2. 响应头 Content-Type -> 作用:告诉浏览器通过什么格式来解析我发给你的数据
            1. text/html
            2. application/json
          1. 空白行
          2. 响应体
    1. http模块的相关代码
      1. 开启一个web服务的核心步骤

    const http = require('http')
    const server = http.createServer()
    server.on('request',(req,res)=>{
    // 1. 如何向响应体中增加数据并结束响应
    res.end('响应体的数据')

    // 2. 如何设置响应头
    //key: Content-Type
    // value: text/html application/json
    // 告诉浏览器解析utf8格式的字符,需要使用 charset=utf-8
    res.setHeader('key','value')

    })

    server.listen(端口,()=>{
    // 成功开启web服务以后会自动执行这个回调函数
    })

相关推荐
神仙别闹4 小时前
基于VUE+Node.JS实现(Web)学生组队网站
前端·vue.js·node.js
BXCQ_xuan5 小时前
基于Node.js的健身会员管理系统的后端开发实践
后端·mysql·node.js
wt_cs6 小时前
身份证实名认证接口数字时代的信任基石-node.js实名认证集成
开发语言·node.js·php
李剑一8 小时前
写一个vitepress新建文章脚本,自动化创建链接,别再手写了!
前端·node.js·vitepress
名字越长技术越强1 天前
Node.js学习
学习·node.js
知识分享小能手1 天前
JavaScript学习教程,从入门到精通,Ajax与Node.js Web服务器开发全面指南(24)
开发语言·前端·javascript·学习·ajax·node.js·html5
dwqqw1 天前
opencv图像库编程
前端·webpack·node.js
layman05281 天前
node.js 实战——(fs模块 知识点学习)
javascript·node.js
本本啊1 天前
node 启动本地应用程序并设置窗口大小和屏幕显示位置
前端·node.js
全栈派森1 天前
Next15 + Prisma + Auth5 实战讲解
react.js·node.js·next.js