day02
需求:
- 基于
info.json
- 随机获取一位小伙伴,count++
- 保存到
info.json
分析:
- 准备工作:
- 导入什么?
- path,fs
- 读取:
- readFileSync->读取出来的默认是 string(JSON)--->对应的数组->JSON.parse
- 业务:
- Math.random()--0-1的小数
- Math.random()*数组length-->转为整数
- 写入:
- writeFileSync--->不能直接写如数组-->转为string--->JSON.stringify
模块化的概念
随着前端代码越来越多,如何更好的拆分,管理代码呢?这里就需要用到模块化咯
概念:
- 把一个大的程序拆分成
互相依赖
的若干小文件 - 这些小文件还可以通过特定的语法组合到一起
- 这个过程称之为模块化
index.html
xxx.js
xx.css
- 优点:
- 更好维护
- 更好的复用性
- 缺点:
- 没有缺点😁
- 学习对应的模块化语法(目前有2种主流,最终会变为一种)
- 文件会很多,初期可能会出现找不到的情况
分析:
- 功能写完只有
10
行代码,模块化没啥必要! - 功能写完有
100
行,或者1000
行代码,里面有好几段
逻辑在其他地方也要用c+v
一把梭?- c+v的逻辑,有一个地方需要调整
- 模块化!!!!
- 逻辑都写在一起,并且越写越多
- 进行模块化之后
Q1:
咱们介绍了什么是模块化,他的优势会在代码逐步增多的情况下逐渐体现:
- 所有逻辑都写在一起,是否可以实现功能?
- 可以--->不好维护
- 模块化可以让代码更好维护,更好___?
- 复用
模块化的规范
前端发展的过程中,出现过一些不同的模块化规范咱们来认识一下他们,不用都掌握,重点学习其中的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(); } });
CommonJS
⇒Node.js
Node.js
是CommonJS
规范的主要实践者- 咱们目前能接触到用
commonJS
规范的也就是Node.js
ESM
- 也叫做
ES6 Module
- ES6 在语言标准的层面上,实现了模块功能,逐步会成为浏览器和服务器通用的模块解决方案👍👍
- 之后基本上所有的代码都是用这个方案!!
- 也叫做
规范:
- 规范的含义:约定了如何导出/导入模块
- 遵守规范,需要实现规范约定的功能
Q2:
咱们介绍了前端开发中出现过的一些不同模块化规范,咱们学习其中两个即可CommonJS,ESM
Node.js
是哪个规范的主要实践者?CommonJS
ESM
也叫做什么?- ES6 Module--->之后的通用解决方案
Node.js中的模块分类
学习了模块化之后,咱们写的JS文件就有了一个更好听的名字-模块。而在Node.js中除了咱们自己写的模块,还有一些其他的模块
Node.js
中的模块主要有3个分类:
- 自定义模块
- NodeJS中,创建的
JS
文件都是自定义模块。(也就是处处皆模块)
- NodeJS中,创建的
- 内置模块(核心模块)
- 安装Node之后,自带了很多内置模块。我们可以直接加载使用他们。
- 第三方模块
- 其他人编写的模块,发布到 npm 网站 上,我们可以下载使用。
Vue-React下载量
npm trends: Compare NPM package downloads
npm包下载统计
npm-stat: download statistics for NPM packages
Q3:
- Node.js中咱们自己的JS文件是什么模块?
- 自定义模块
- Node.js中的模块还有哪些分类?
- 内置
- 第三方
CommonJS模块
Node.js是CommonJS规范的主要实践者,咱们需要如何使用呢?
模块作用域
- 在
Node.js
中,用户创建的每个.js
文件都是自定义模块。 - 在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问
- 这种模块级别的访问限制,叫做模块作用域。
- 正因为如此,才需要导入/导出
语法:
- 通过module.exports导出(暴露)内容
module
是Node中的一个全局对象,对象包含当前模块的详细信息。module.exports
是模块的出口,通俗的说,就是导出内容用的,默认值是{}
- 通过require加载内容
require
是Node
中的一个全局方法,可以用来导入模块const 结果 = require('模块路径')
- 只能加载模块暴露的内容
测试:
- 创建模块
/module/myModule.js
- 添加变量,方法,并通过
module.exports
导出 - 通过
require
导入模块 - 测试能否获取导出的内容
Q:4 核心就是导入和导出
CommonJS
中导出模块的语法是?module.exports
CommonJS
中加载(导入)模块的语法是?require
数据模块-封装
基于刚刚学习的知识,咱们来封装一个功能模块
需求:
- 基于提供的数据实现
db
模块- 调用方法,返回对应的数据
- 数据在
02-其他资料
中
const db = require('db.js')
db.news() // 返回新闻数据 数组
db.students() // 返回 所有的同学信息 数组
db.luckystar()// 返回随机的同学 对象 count累加,保存回数据
分析:
准备
需要导入什么?
fs,path(绝对路径)
逻辑:
news()
:绝对路径-->读取(新闻)->转数组->返回students()
:绝对路径-->读取(学员)->转数组->返回luckystar()
:绝对路径-->读取(学员)->转数组->随机->count++->返回同学->保存回去
导出:
Q:5
咱们基于提供的数据封装了一个数据模块
- 封装的目的是?
- 方便复用,更好维护
- 使用封装好的模块时是否需要看懂源码?
- 只需要知道:方法-->功能
npm
npm是什么?
开发中一般不会什么功能都自己写,如何优雅的下载第三方模块呢?---npm
- npm 是 管理(下载、卸载、发布)第三方模块的工具。
npm
(node package manager)node 包管理工具。管理node包的工具。- 包是什么?包就是模块。(包约等于模块,一个包可以包括一个或多个模块)
- npm这个工具,在安装 node 的时候,就已经安装到你的计算机中了。(捆绑安装)
- 命令行中执行:
npm -v
,如果看到版本号,说明安装成功了。
npm是什么?
刚才介绍了之后会经常使用的一个包管理工具-npm
npm
是什么?- node的包管理工具
- 前端的第三方模块.也可以用它下载
- 输入什么命令可以确认
npm
的版本?npm -v
npm基本使用
上一节介绍了npm的概念,如何使用他呢?
淘宝镜像站
# 设置淘宝镜像,设置了之后,安装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
# 通过cnpm 安装模块
# 或者使用cnpm ==> 以后使用 cnpm 安装,使用国内镜像站
npm install -g cnpm --registry=https://registry.npmmirror.com
# 查看cnpm
cnpm -v # 以后可以使用
# 安装新模块
cnpm install xxx
新建文件夹,初始化项目
基本步骤:
- 初始化项目
- 下载需要的第三方模块
详细步骤:
初始化命令的两种写法
npm init -y
# 或
npm init
# 然后一路回车
注意:
npm init
默认会读取文件夹名作为项目名 ==> package name
- package name
- 不能有中文
- 不能有特殊符号
- 不能和需要安装的第三方模块同名
初始化之后,会在项目目录中生成
package.json
的文件。初始化完毕之后就可以在当前文件夹安装第三方模块
- 为了保证安装速度,建议执行这个命令
- 命令的作用是切换第三方模块的下载地址为
淘宝镜像
bash建议在安装第三方模块之前,先执行如下命令。 下面的命令只需要执行一次即可(不管以后重启vscode还是重启电脑,都不需要执行第二次) npm config set registry https://registry.npmmirror.com
下载的命令
bash# 正常的下载安装 npm install 模块名 # 简写install为i npm i 模块名 # 一次性安装多个模块 npm i 模块名 模块名 模块名 # 可以通过@版本号,不设置默认是最新 npm i 模块名@版本号
卸载的命令
bashnpm uninstall 模块名 npm un 模块名 npm un 模块名 模块名 模块名
测试
下载
和卸载
axios
dayjs
观察下载之后项目中下列文件发生的变化
package.json
- 保存下载的模块信息
package-lock.json
node_modules
Q6:
npm
初始化的项目名是否有要求?- 不能为中文,不能有特殊符号,大写字母⇒ 小写
- 下载模块的命令是?
- npm i 模块名
- npm i 模块名@版本号
- 移除模块的命令是?
- npm un 模块名
dayjs-基本使用
上一节咱们下载了dayjs,咱们来看看这个库的作用是什么,并且来测试一下
dayjs格式
https://dayjs.fenxianglu.cn/category/display.html#格式化
⇒ 注意大小写!! 不能修改
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
需求:
- 根据文档确认用法并测试使用
- 将提供数据中的日期转为
2022-07-18 17:35:53
这种格式
步骤:
参考文档,测试并使用
将如下时间戳转为
YYYY-MM-DD HH:mm:ss
这种格式bash1668640759762
Q7:dayjs-基本使用
这一小节咱们学习了日期格式化库-dayjs
的基本使用:
- 任何库的使用套路都是类似的:
- 基于文档的示例->c+v运行
- 根据文档,传入不同的参数
- 如何进阶?
- 基本使用:入门
- 重度使用:熟练-->精通→
- 修复框架/库的bug:开源框架贡献者
- 实现框架/库:开源框架作者
小结
- 模块化
- 作用:
- 大的-->小的
- 小-->组合到一起
- 规范:
- CommonJS
- ESM
- 语法:
- module.exports--->导出(暴露)
- require()-->导入
- 只能在
Node.js
中
- 作用:
- npm:
- 查看版本:
npm -v
- 下包:
npm i 包名
npm i 包名@版本号
- 用包
- 跟着文档使用--
dayjs
- 跟着文档使用--
- 删包
npm un 包名
- 查看版本:
package.json和package-lock.json的作用
项目中中多出来的package.json和package-lock.json的作用是什么呢?
package.json
保存项目的信息:
name
:项目名version
:项目版本description
:项目描述main
:项目入口scripts
:- 示例中的:
test
可以通过npm run test
执行
- 示例中的:
author
:作者license
:开源协议dependencies
:项目中用到的第三方模块(依赖)
{
"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
- 更为详细的第三方模块模块
- 版本信息
- 甚至下载地址
- ...
实际应用
- 共享的
node
项目一般会删除node_modules
- 只要项目目录中有
package.json
说明项目是完整的 - 项目根目录,执行
npm i
即可读取package.json
中保存的dependencies
(依赖信息),重新下载- 命令执行的目录和
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
中保存的依赖信息,并下载?npm i
- 执行这个命令对路径是否有要求?
- 和
package.json
同级
- 和
全局模块
第三方模块除了项目中直接下载使用的模块以外,还有一种叫做全局模块的,咱们来认识一下,并且安装几个试试
和本地模块的差异
- 全局安装的模块,不能通过
require()
加载使用。 - 全局安装的模块,一般都是命令或者工具。
安装卸载命令
安装命令(多一个
g
)bashnpm i 模块名 -g # 或 npm i -g 模块名 ### mac 系统如果安装不上,使用下面的命令提高权限 sudo npm i -g 模块名
卸载命令(也是多一个
g
)bashnpm un 模块名 -g # 或者 npm uninstall 模块名 -g
全局安装的模块,在系统盘(C盘)
- 通过命令
npm root -g
可以查看全局安装路径
- 通过命令
nrm介绍
nrm
是作用是切换镜像源(模块下载地址;模块下载的网站)。
nrm安装
- 执行命令
- 不需要记忆哪些模块需要
g
或者不需要 - 直接可以通过官方文档确认
- 不需要记忆哪些模块需要
npm i nrm -g (mac系统前面加 sudo)
- 使用
nrm
nrm --help # 查看帮助
nrm ls # 查看全部可用的镜像源
nrm test # 测试各个源的速度
nrm use taobao # 切换到淘宝镜像
nrm use npm # 切换到npm主站
Serve
- 功能和昨天自己编写的web服务器类似
- 参考文档安装+使用
- 分别将
- clock和数据可视化
- 通过
serve
托管并测试访问
常见错误及解决方案:
mac
安装:- sudo npm i -g nrm
- 输入密码:
运行
nrm ls
或者nrm use taobao
等命令,如果报错如下:“无法加载文件 C:......................,因为在此系统上禁止运行脚本。................”
- 解决办法:
管理员
方式,打开命令行(powershell)窗口- 执行
set-ExecutionPolicy RemoteSigned;
- 在出现的选项中,输入
A
,回车。即可。
- 解决办法:
如果报错如下: “无法将 nrm 识别为 cmdlet、函数、脚本文件或可运行程序的名称。xxxxxxxxxxx”
- 解决办法:
- 重启vscode,win7可能要重启电脑。
- 解决办法:
Q
咱们安装并使用了几个全局模块:
- 全局模块在安装命令是?比如安装
nrm
模块npm i nrm -g
- 如何确认某个模块是全局模块还是本地模块?
写接口
基于目前完成的内容,来实现一个返回数据的接口,并测试调用
需求:
- 请求方法统一为
get
/api/news
返回新闻数据(日期转为2022-07-18 17:35:53
)/api/students
返回全部同学/api/luckystar
返回随机的同学
基础模板:
- 这部分内容直接c+v
// 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')
// 不能直接响应 对象/数组 需要转为字符串
})
分析:
- 接收
- 如何判断请求方法?
request.method
- 如何判断请求地址?
request.url
- 如何判断请求方法?
- 响应
- 如何获取对应的数据?
- 调用封装的
db
数据模块的对应方法
- 调用封装的
- 如何响应内容?
response.end()
- 如何获取对应的数据?
- 逻辑:
/api/students
- 返回
db.students()
- 返回
/api/luckystar
- 返回
db.luckystar()
- 返回
/api/news
- 转化
dayjs(时间戳).format('YYYY-MM-DD HH:mm:ss')
- 转化
测试:
运行本节代码
node xxx.js
网页直接打开接口
JSON
美化需要安装插件
用接口测试工具测试
写个页面来测试:
- 会报错
写接口
咱们是前端开发工程师,虽然这一节咱们自己实现了几个简单的接口:
- 工作中是否需要咱们写接口?
- 不需要--后端
- 本节写接口的目的是?
- 理解后端的接口大概的工作流程, 核心就是请求过来了,搞到数据给到前端~
同源&跨域
同源和同源策略
刚才的接口之所以调用不了,原因就是因为打开的页面和接口不同源, 咱们来介绍一下什么是同源,以及浏览器的同源策略
同源
同源指的是两个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:**请求的资源地址(接口地址)
Q:
- 同源指的是哪些相同?
- 协议/主机/端口 ⇒ 协议,域名,端口号
- 如果没有浏览器,还会有同源策略吗?
- 没有-->浏览器的限制
跨域及主流跨域方法
有了同源安全策略之后,只要2个不同源就会涉及到跨域
概念:
- 同源指的是两个 URL 的协议、域名、端口号完全一致
- 反之,则是跨域。
- 浏览器的同源策略不允许非同源的 URL 之间进行资源的交互。例如:
- 网页:http://www.test.com/index.html
- 接口:http://www.api.com/userlist
浏览器对跨域请求的拦截过程?
浏览器允许发起跨域请求。但跨域请求回来的数据,会被浏览器拦截,无法被页面获取到!示意图如下:
主流跨域方法
代理服务器 和 CORS 是目前最为流行的实现跨域数据请求的两种技术方案。
- CORS 是跨域的主流技术解决方案
- 代理服务器跨域在后面vue课程中会讲到--Vue的第二个项目(人资)
- 还有一些其他的跨域方案---传送门
如何允许跨源访问
可以使用 CORS 来允许跨源访问。CORS 是 HTTP 的一部分,它允许服务端来指定哪些主机可以从这个服务端加载资源。
CORS
接下来咱们就来介绍一下什么是CORS,以及在Node.js中如何使用它
传送门:CORS ⇒ 跨源资源共享
概念
CORS
是解决跨域数据请求的终极解决方案,全称是Cross-origin resource sharing
。CORS
技术需要浏览器和服务器同时支持
- 浏览器要支持 CORS 功能(主流的浏览器全部支持,IE 不能低于 IE10)
- 前端开发者什么不都需要做
- 服务器要开启 CORS 功能(需要后端开发者为接口开启 CORS 功能)
工作原理
服务器端通过 Access-Control-Allow-Origin
响应头,来告诉浏览器当前的 API 接口是否允许跨域请求。
检查一下之前调用的接口是否有该响应头:
主要优势
- CORS 是真正的 Ajax 请求,支持 GET、POST、DELETE、PUT、PATCH 等这些常见的 Ajax 请求方式
- 只需要后端开启
CORS
功能即可,前端的代码无须做任何改动 Node.js
中可以通过设置如下的请求头允许跨域,添加到响应之前
response.setHeader('Access-Control-Allow-Origin', '*')