Skip to content

day02

需求:

  1. 基于info.json
  2. 随机获取一位小伙伴,count++
  3. 保存到info.json

分析:

  1. 准备工作:
    1. 导入什么?
    2. path,fs
  2. 读取:
    1. readFileSync->读取出来的默认是 string(JSON)--->对应的数组->JSON.parse
  3. 业务:
    1. Math.random()--0-1的小数
    2. Math.random()*数组length-->转为整数
  4. 写入:
    1. writeFileSync--->不能直接写如数组-->转为string--->JSON.stringify

模块化的概念

随着前端代码越来越多,如何更好的拆分,管理代码呢?这里就需要用到模块化咯

传送门:掘金前端模块化详解

概念:

  1. 把一个大的程序拆分成互相依赖的若干小文件
  2. 这些小文件还可以通过特定的语法组合到一起
  3. 这个过程称之为模块化
    1. index.html
      1. xxx.js
      2. xx.css
  4. 优点:
    1. 更好维护
    2. 更好的复用性
  5. 缺点:
    1. 没有缺点😁
    2. 学习对应的模块化语法(目前有2种主流,最终会变为一种)
    3. 文件会很多,初期可能会出现找不到的情况

分析:

  1. 功能写完只有10行代码,模块化没啥必要!
  2. 功能写完有100行,或者1000行代码,里面有好几段逻辑在其他地方也要用
    1. c+v一把梭?
      1. c+v的逻辑,有一个地方需要调整
    2. 模块化!!!!
  3. 逻辑都写在一起,并且越写越多

Untitled

  1. 进行模块化之后

Untitled

Q1:

咱们介绍了什么是模块化,他的优势会在代码逐步增多的情况下逐渐体现:

  • 所有逻辑都写在一起,是否可以实现功能?
    1. 可以--->不好维护
  • 模块化可以让代码更好维护,更好___?
    1. 复用

模块化的规范

前端发展的过程中,出现过一些不同的模块化规范咱们来认识一下他们,不用都掌握,重点学习其中的2个

传送门:前端模块化

前端模块化规范:

  • AMD:--知道名字即可

    • AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。
    • 聊到AMD主要指的是通过require.js实现的模块化
    • 项目中看到类似代码说明用的是AMD规范
    • 目前用的很少很少,了解即可
    // 执行基本操作
    require(["jquery","underscore"],function($,_){
      // some code here
    });
  • CMD:--目前没人用了

    • CMD是另一种js模块化方案,它与AMD很类似。
    • 不同点在于:AMD 推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行。
    • 项目中看到类似代码说明用的是CMD规范
    • 目前用的很少很少了解即可(sea.js)
    define(function(require, exports, module) {
        var a = require('./a'); //在需要时申明
        a.doSomething();
        if (false) {
            var b = require('./b');
            b.doSomething();
        }
    });
  • CommonJSNode.js

    • Node.jsCommonJS规范的主要实践者
    • 咱们目前能接触到用commonJS规范的也就是Node.js
  • ESM

    • 也叫做ES6 Module
    • ES6 在语言标准的层面上,实现了模块功能,逐步会成为浏览器服务器通用的模块解决方案👍👍
    • 之后基本上所有的代码都是用这个方案!!

规范:

  1. 规范的含义:约定了如何导出/导入模块
  2. 遵守规范,需要实现规范约定的功能

Q2:

咱们介绍了前端开发中出现过的一些不同模块化规范,咱们学习其中两个即可CommonJS,ESM

  • Node.js是哪个规范的主要实践者?
    1. CommonJS
  • ESM也叫做什么?
    1. ES6 Module--->之后的通用解决方案

Node.js中的模块分类

学习了模块化之后,咱们写的JS文件就有了一个更好听的名字-模块。而在Node.js中除了咱们自己写的模块,还有一些其他的模块

Untitled

Node.js中的模块主要有3个分类:

  • 自定义模块
    • NodeJS中,创建的JS文件都是自定义模块。(也就是处处皆模块)
  • 内置模块(核心模块)
    • 安装Node之后,自带了很多内置模块。我们可以直接加载使用他们。
  • 第三方模块
    • 其他人编写的模块,发布到 npm 网站 上,我们可以下载使用。

Vue-React下载量

npm trends: Compare NPM package downloads

Untitled

npm包下载统计

npm-stat: download statistics for NPM packages

Q3:

  • Node.js中咱们自己的JS文件是什么模块?
    1. 自定义模块
  • Node.js中的模块还有哪些分类?
    1. 内置
    2. 第三方

CommonJS模块

Node.js是CommonJS规范的主要实践者,咱们需要如何使用呢?

传送门:Node.js-CommonJS模块

模块作用域

  • Node.js 中,用户创建的每个 .js 文件都是自定义模块
  • 在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问
  • 这种模块级别的访问限制,叫做模块作用域
  • 正因为如此,才需要导入/导出

语法:

  1. 通过module.exports导出(暴露)内容
    1. module 是Node中的一个全局对象,对象包含当前模块的详细信息。
    2. module.exports 是模块的出口,通俗的说,就是导出内容用的,默认值是 {}
  2. 通过require加载内容
    1. requireNode中的一个全局方法,可以用来导入模块
    2. const 结果 = require('模块路径')
    3. 只能加载模块暴露的内容

测试:

  1. 创建模块/module/myModule.js
  2. 添加变量,方法,并通过module.exports导出
  3. 通过require导入模块
  4. 测试能否获取导出的内容

Q:4 核心就是导入导出

  • CommonJS导出模块的语法是?
    1. module.exports
  • CommonJS中加载(导入)模块的语法是?
    1. require

数据模块-封装

基于刚刚学习的知识,咱们来封装一个功能模块

需求:

  1. 基于提供的数据实现db模块
    1. 调用方法,返回对应的数据
  2. 数据在02-其他资料
tsx
const db = require('db.js')
db.news() // 返回新闻数据 数组
db.students() // 返回 所有的同学信息 数组
db.luckystar()// 返回随机的同学 对象 count累加,保存回数据

分析:

  1. 准备

    1. 需要导入什么?

      fs,path(绝对路径)

  2. 逻辑:

    1. news():绝对路径-->读取(新闻)->转数组->返回
    2. students():绝对路径-->读取(学员)->转数组->返回
    3. luckystar():绝对路径-->读取(学员)->转数组->随机->count++->返回同学->保存回去
  3. 导出:

Q:5

咱们基于提供的数据封装了一个数据模块

  • 封装的目的是?
    1. 方便复用,更好维护
  • 使用封装好的模块时是否需要看懂源码?
    1. 只需要知道:方法-->功能

npm

npm是什么?

开发中一般不会什么功能都自己写,如何优雅的下载第三方模块呢?---npm

传送门:如何使用npm

  • npm 是 管理(下载、卸载、发布)第三方模块的工具。
  • npm(node package manager)node 包管理工具。管理node包的工具。
  • 是什么?包就是模块。(包约等于模块,一个包可以包括一个或多个模块)
  • npm这个工具,在安装 node 的时候,就已经安装到你的计算机中了。(捆绑安装)
  • 命令行中执行: npm -v ,如果看到版本号,说明安装成功了。

https://www.notion.so

npm是什么?

刚才介绍了之后会经常使用的一个包管理工具-npm

  • npm是什么?
    1. node的包管理工具
    2. 前端的第三方模块.也可以用它下载
  • 输入什么命令可以确认npm的版本?
    1. npm -v

npm基本使用

上一节介绍了npm的概念,如何使用他呢?

传送门:淘宝镜像站更换新域名啦

淘宝镜像站

npmmirror 中国镜像站

bash
# 设置淘宝镜像,设置了之后,安装node模块,从国内镜像下载
npm config set registry https://registry.npmmirror.com

# 查看npm地址
npm config get registry

# 还原 node.js在某些版本下,安装国内镜像可能或报错,还原回npm服务器
npm config set registry https://registry.npmjs.org
bash
# 通过cnpm 安装模块 
# 或者使用cnpm  ==> 以后使用 cnpm 安装,使用国内镜像站
npm install -g cnpm --registry=https://registry.npmmirror.com
# 查看cnpm 
cnpm -v # 以后可以使用 
# 安装新模块 
cnpm install xxx

新建文件夹,初始化项目

基本步骤:

  1. 初始化项目
  2. 下载需要的第三方模块

详细步骤:

初始化命令的两种写法

bash
npm init -y
# 或
npm init
# 然后一路回车

注意:

npm init默认会读取文件夹名作为项目名 ==> package name

  • package name
    • 不能有中文
    • 不能有特殊符号
    • 不能和需要安装的第三方模块同名
  1. 初始化之后,会在项目目录中生成 package.json 的文件。

  2. 初始化完毕之后就可以在当前文件夹安装第三方模块

    1. 为了保证安装速度,建议执行这个命令
    2. 命令的作用是切换第三方模块的下载地址为淘宝镜像
    bash
    建议在安装第三方模块之前,先执行如下命令。
    下面的命令只需要执行一次即可(不管以后重启vscode还是重启电脑,都不需要执行第二次)
    npm config set registry https://registry.npmmirror.com
  3. 下载的命令

    bash
    # 正常的下载安装
    npm install 模块名
    
    # 简写install为i
    npm i 模块名
    
    # 一次性安装多个模块
    npm i 模块名 模块名 模块名
    # 可以通过@版本号,不设置默认是最新
    npm i 模块名@版本号
  4. 卸载的命令

    bash
    npm uninstall 模块名
    npm un 模块名
    npm un 模块名 模块名 模块名
  5. 测试下载卸载

    1. axios
    2. dayjs
  6. 观察下载之后项目中下列文件发生的变化

    1. package.json
      1. 保存下载的模块信息
    2. package-lock.json
    3. node_modules

Q6:

  • npm初始化的项目名是否有要求?
    1. 不能为中文,不能有特殊符号,大写字母⇒ 小写
  • 下载模块的命令是?
    1. npm i 模块名
    2. npm i 模块名@版本号
  • 移除模块的命令是?
    1. npm un 模块名

dayjs-基本使用

上一节咱们下载了dayjs,咱们来看看这个库的作用是什么,并且来测试一下

传送门:dayjs

传送门:解析规则

dayjs格式

https://dayjs.fenxianglu.cn/category/display.html#格式化

⇒ 注意大小写!! 不能修改

tsx
dayjs().format();                                     // 2020-09-08T13:42:32+08:00
dayjs().format('YYYY-MM-DD');                         // 2020-09-08
dayjs().format('YYYY-MM-DD HH:mm:ss');                // 2020-09-08 13:47:12
dayjs(1318781876406).format('YYYY-MM-DD HH:mm:ss');   // 2011-10-17 00:17:56

需求:

  1. 根据文档确认用法并测试使用
  2. 将提供数据中的日期转为2022-07-18 17:35:53这种格式

步骤:

  1. 参考文档,测试并使用

  2. 将如下时间戳转为YYYY-MM-DD HH:mm:ss这种格式

    bash
    1668640759762

Q7:dayjs-基本使用

这一小节咱们学习了日期格式化库-dayjs的基本使用:

  • 任何库的使用套路都是类似的:
    1. 基于文档的示例->c+v运行
    2. 根据文档,传入不同的参数
  • 如何进阶?
    1. 基本使用:入门
    2. 重度使用:熟练-->精通→
    3. 修复框架/库的bug:开源框架贡献者
    4. 实现框架/库:开源框架作者

小结

  1. 模块化
    1. 作用:
      1. 大的-->小的
      2. 小-->组合到一起
    2. 规范:
      1. CommonJS
      2. ESM
    3. 语法:
      1. module.exports--->导出(暴露)
      2. require()-->导入
      3. 只能在Node.js
  2. npm:
    1. 查看版本:npm -v
    2. 下包:
      1. npm i 包名
      2. npm i 包名@版本号
    3. 用包
      1. 跟着文档使用--dayjs
    4. 删包
      1. npm un 包名

package.json和package-lock.json的作用

项目中中多出来的package.json和package-lock.json的作用是什么呢?

传送门:package.json

传送门:package-lock.json

传送门:详解package.json和package-lock.json

package.json

保存项目的信息:

  1. name:项目名
  2. version:项目版本
  3. description:项目描述
  4. main:项目入口
  5. scripts:
    1. 示例中的:test可以通过npm run test执行
  6. author:作者
  7. license:开源协议
  8. dependencies:项目中用到的第三方模块(依赖)
json
{
  "name": "03",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "dayjs": "^1.11.0",
    "jquery": "^3.6.0"
  }
}

package-lock.json

  1. 更为详细的第三方模块模块
    1. 版本信息
    2. 甚至下载地址
    3. ...

实际应用

  1. 共享的node项目一般会删除node_modules
  2. 只要项目目录中有package.json说明项目是完整的
  3. 项目根目录,执行npm i即可读取package.json中保存的dependencies(依赖信息),重新下载
    1. 命令执行的目录和package.json同级

PS.版本号

语义版本控制

首先我们先来了解下依赖包的版本号的定义

版本号由三部分组成:major.minor.patch,主版本号.次版本号.修补版本号。

例如:1.2.3,主要版本1,次要版本2,补丁3。

  • 补丁中的更改表示不会破坏任何内容的错误修复。
  • 次要版本的更改表示不会破坏任何内容的新功能。
  • 主要版本的更改代表了一个破坏兼容性的大变化。 如果用户不适应主要版本更改,则内容将无法正常工作。

安装依赖包的版本如何指定

相信大家都会经历过,我们安装一些依赖包的时候,版本号前面都会带 ^ 或者 ~ 的符号,这两个符号代表什么意思呢?

~ 会匹配最近的小版本依赖包,比如 ~1.2.3 会匹配所有 1.2.x 版本,但是不包括 1.3.0

^ 会匹配最新的大版本依赖包,比如 ^1.2.3 会匹配所有 1.x.x 的包,包括 1.3.0,但是不包括 2.0.0

Q8:

  • 哪个命令会读取package.json中保存的依赖信息,并下载?
    1. npm i
  • 执行这个命令对路径是否有要求?
    1. package.json同级

全局模块

第三方模块除了项目中直接下载使用的模块以外,还有一种叫做全局模块的,咱们来认识一下,并且安装几个试试

传送门:nrm官网

传送门:serve

和本地模块的差异

  • 全局安装的模块,不能通过 require() 加载使用。
  • 全局安装的模块,一般都是命令或者工具。

安装卸载命令

  • 安装命令(多一个 g

    bash
    npm i 模块名 -g
    # 或
    npm i -g 模块名
    
    ### mac 系统如果安装不上,使用下面的命令提高权限
    sudo npm i -g 模块名
  • 卸载命令(也是多一个 g

    bash
    npm un 模块名 -g
    # 或者
    npm uninstall 模块名 -g
  • 全局安装的模块,在系统盘(C盘)

    • 通过命令 npm root -g 可以查看全局安装路径

nrm介绍

nrm 是作用是切换镜像源(模块下载地址;模块下载的网站)。

Untitled

nrm安装

  1. 执行命令
    1. 不需要记忆哪些模块需要g或者不需要
    2. 直接可以通过官方文档确认
bash
npm i nrm -g (mac系统前面加 sudo)
  1. 使用nrm
bash
nrm --help   # 查看帮助
nrm ls    # 查看全部可用的镜像源
nrm test # 测试各个源的速度
nrm use taobao  # 切换到淘宝镜像
nrm use npm  # 切换到npm主站

Serve

  1. 功能和昨天自己编写的web服务器类似
  2. 参考文档安装+使用
  3. 分别将
    1. clock数据可视化
    2. 通过serve托管并测试访问

常见错误及解决方案:

  • mac安装:

    • sudo npm i -g nrm
    • 输入密码:
  • 运行 nrm ls 或者 nrm use taobao 等命令,如果报错如下:

    “无法加载文件 C:......................,因为在此系统上禁止运行脚本。................”

    • 解决办法:
      • 管理员方式,打开命令行(powershell)窗口
      • 执行 set-ExecutionPolicy RemoteSigned;
      • 在出现的选项中,输入 A,回车。即可。
  • 如果报错如下: “无法将 nrm 识别为 cmdlet、函数、脚本文件或可运行程序的名称。xxxxxxxxxxx”

    • 解决办法:
      • 重启vscode,win7可能要重启电脑。

Q

咱们安装并使用了几个全局模块:

写接口

基于目前完成的内容,来实现一个返回数据的接口,并测试调用

需求:

  1. 请求方法统一为get
  2. /api/news返回新闻数据(日期转为2022-07-18 17:35:53)
  3. /api/students返回全部同学
  4. /api/luckystar返回随机的同学

基础模板:

  • 这部分内容直接c+v
tsx
// 1. 导入 http 模块
const http = require('http')

// 2. 创建 web 服务器实例
const server = http.createServer()

// 3. 启动服务器
server.listen(8848, () => {
  console.log('my server start work')
})

// 4. 为服务器实例绑定 request 事件,监听客户端的请求
server.on('request', (request, response) => {
  // 设置响应的内容为JSON
 response.setHeader('Content-Type', 'application/json; charset=utf-8')
  // 不能直接响应 对象/数组 需要转为字符串
})

分析:

  1. 接收
    1. 如何判断请求方法?request.method
    2. 如何判断请求地址?request.url
  2. 响应
    1. 如何获取对应的数据?
      1. 调用封装的db数据模块的对应方法
    2. 如何响应内容?
      1. response.end()
  3. 逻辑:
    1. /api/students
      1. 返回db.students()
    2. /api/luckystar
      1. 返回db.luckystar()
    3. /api/news
      1. 转化dayjs(时间戳).format('YYYY-MM-DD HH:mm:ss')

测试:

  1. 运行本节代码

    1. node xxx.js
  2. 网页直接打开接口

    1. JSON美化需要安装插件
  3. 用接口测试工具测试

  4. 写个页面来测试:

    1. 会报错

    Untitled

写接口

咱们是前端开发工程师,虽然这一节咱们自己实现了几个简单的接口:

  • 工作中是否需要咱们写接口?
    1. 不需要--后端
  • 本节写接口的目的是?
    1. 理解后端的接口大概的工作流程, 核心就是请求过来了,搞到数据给到前端~

同源&跨域

同源和同源策略

刚才的接口之所以调用不了,原因就是因为打开的页面和接口不同源, 咱们来介绍一下什么是同源,以及浏览器的同源策略

同源

同源指的是两个URL地址具有相同的协议主机端口号。⇒ (协议,域名,端口)

相对于 http://www.test.com/index.html 页面的 5 个同源检测结果:

URL是否同源原因
http://www.test.com/other.html同源端口默认都是80
https://www.test.com/about.html协议不同
http://blog.test.com/movie.html主机不同
http://www.test.com:7001/home.html端口不同
http://www.test.com:80/main.html同源http:不写也是80

什么是同源策略?

同源策略(英文全称 Same origin policy)是浏览器提供的一个安全功能。 浏览器的同源策略规定:不允许非同源的 URL 之间进行资源的交互。

地址1: 网页的URL

**地址2:**请求的资源地址(接口地址)

Untitled

Q:

  • 同源指的是哪些相同?
    • 协议/主机/端口 ⇒ 协议,域名,端口号
  • 如果没有浏览器,还会有同源策略吗?
    • 没有-->浏览器的限制

跨域及主流跨域方法

有了同源安全策略之后,只要2个不同源就会涉及到跨域

概念:

浏览器对跨域请求的拦截过程?

浏览器允许发起跨域请求。但跨域请求回来的数据,会被浏览器拦截,无法被页面获取到!示意图如下:

Untitled

主流跨域方法

代理服务器CORS 是目前最为流行的实现跨域数据请求的两种技术方案。

  1. CORS 是跨域的主流技术解决方案
  2. 代理服务器跨域在后面vue课程中会讲到--Vue的第二个项目(人资)
  3. 还有一些其他的跨域方案---传送门

如何允许跨源访问

可以使用 CORS 来允许跨源访问。CORS 是 HTTP 的一部分,它允许服务端来指定哪些主机可以从这个服务端加载资源。

CORS

接下来咱们就来介绍一下什么是CORS,以及在Node.js中如何使用它

传送门:CORS ⇒ 跨源资源共享

概念

  1. CORS 是解决跨域数据请求的终极解决方案,全称是 Cross-origin resource sharing
  2. CORS 技术需要浏览器服务器同时支持
  • 浏览器要支持 CORS 功能(主流的浏览器全部支持,IE 不能低于 IE10)
    • 前端开发者什么不都需要做
  • 服务器要开启 CORS 功能(需要后端开发者为接口开启 CORS 功能)

工作原理

服务器端通过 Access-Control-Allow-Origin 响应头,来告诉浏览器当前的 API 接口是否允许跨域请求。

Untitled

检查一下之前调用的接口是否有该响应头:

主要优势

  1. CORS 是真正的 Ajax 请求,支持 GET、POST、DELETE、PUT、PATCH 等这些常见的 Ajax 请求方式
  2. 只需要后端开启 CORS 功能即可,前端的代码无须做任何改动
  3. Node.js中可以通过设置如下的请求头允许跨域,添加到响应之前
tsx
response.setHeader('Access-Control-Allow-Origin', '*')