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服务以后会自动执行这个回调函数
    })

相关推荐
narukeu19 小时前
对于 TypeORM 精准&模糊查询的简单二次封装
typescript·node.js·express·typeorm
哟哟耶耶1 天前
npm-npm install时rollbackFailedOptional: verb npm-session ce210dc17dd264aa报错
前端·npm·node.js
m0_748248771 天前
最新最详细的配置Node.js环境教程
node.js
大梦百万秋1 天前
从零开始搭建一个RESTful API(Node.js + Express)
node.js·restful·express
Libby博仙1 天前
VUE3 常用的组件介绍
前端·javascript·vue.js·前端框架·npm·node.js
至少零下七度1 天前
npm : 无法加载文件 D:\SoftFile\npm.ps1,因为在此系统上禁止运行脚本。
前端·npm·node.js
Libby博仙1 天前
VUE3 VITE项目在 npm 中,关于 Vue 的常用命令有一些基础命令
前端·vue.js·npm·node.js
Libby博仙1 天前
VUE3 一些常用的 npm 和 cnpm 命令,涵盖了修改源、清理缓存、修改 SSL 协议设置等内容。
缓存·npm·node.js·vue·ssl
来吧~1 天前
webpack常见优化方法
前端·webpack·node.js