GET请求和POST请求
GET请求发生的场景:
1.在浏览器地址栏输入网址,然后点击回车,会给该网址发送GET请求
2.点击a标签链接,会给a标签绑定的URL发送GET请求
3.LINK标签引入的CSS,如果CSS是URL,会给该URL发送GET请求
4.script标签引入的js,如果js是URL,会给该URL发送GET请求
5.video/audio引入多媒体,如果引入地址是URL,会给该URL发送GET请求
6.img标签引入图片,如果地址绑定是URL,会给该URL发送GET请求
7.form标签中的method为GET时
8.ajax中的get请求
POST请求发生的场景:
1.ajax的POST请求
2.form标签中的method为POST
3。前后端接口请求,前端向后端传数据时,一般是POST
GET请求和POST请求的对比:
1.GET请求一般用来获取数据,POST请求主要用来提交数据(一般是这样,但是也可以用GET提交数据)
2.参数位置:GET请求参数一般在URL内,以params的形式传输。POST的请求则会放到请求体里,是payload的形式(一般是这样,但是用法也可以互换)
3.安全:POST相对GET安全一些。GET会在URL地址里暴露一些信息(相对来说,如果抓HTTP请求,对请求体进行分析,也能看到POST传输的数据)
4.请求大小:GET由于需要把信息放到URL,一般不会超过2K。POST则可以传输更多信息。
模块化
随着项目的功能加多,项目复杂性也会变高,代码量也会越来越高,如果把代码都放在一个地方,不便于维护和阅读。
基于这些问题,把一个复杂的文件,按照一定的规则拆分成多个文件,对其进行管理,这就是模块化的思想。
拆分出的每一个文件都是一个模块。最后再把模块按照一定的规则组合起来,完成同样的功能效果。
模块内部的数据是该模块私有的,但是模块可以通过暴露的方式把自己的数据交给其他模块使用。
项目模块化
在编写项目时,项目代码是按照模块化的思想来写的,这个项目就是一个模块化的项目。
模块化优点
1.高复用性(模块化代码可以暴露给其他模块使用)
2.高维护性(当项目需要多人开发时,多人对同一个文件进行编辑会发生频繁的冲突。在对项目进行升级或者修复时,也可以按模块进行)
3.可阅读性(模块化项目便于管理和阅读)
4.缓解命名冲突(对于单文件模式,一个文件内部不能包含一样的命名,但是如果使用模块化思想,则可以通过命名空间等方式让不同的变量在各自的空间内可以同名)
简单例子

a.js
javascript
function aMethod(){
console.log('a------')
}
module.exports = aMethod
b.js
javascript
const aMethod = require('./a.js')
console.log(aMethod)
aMethod()

模块的暴露与导入
暴露数据
使用module.exports可以默认暴露函数,但是,如果一个模块中有两个函数,我想同时暴露两个函数,应该如何做呢?
1.一个方法是默认暴露一个对象,对象中包含这两个方法

a.js
javascript
function aMethod(){
console.log('a------')
}
function aMethod2(){
console.log('have a nice day : )')
}
module.exports = {
aMethod,
aMethod2
}
b.js
javascript
const aMethod = require('./a.js')
console.log(aMethod)
aMethod.aMethod()
aMethod.aMethod2()

2.一个是使用exports.暴露方法 exports.属性名 = 属性值,该方法的效果和默认暴露是一样的,在js内部,存在关系exports = module.exports = {},而require在返回值时,返回的是module.exports的值。
当通过exports.属性名 = 属性值 操作时,实际上是往module.exports绑定的对象里添加方法。所以不要通过exports = 这样的语法来对外暴露,它并不会生效。

a.js
javascript
function aMethod(){
console.log('a------')
}
function aMethod2(){
console.log('have a nice day : )')
}
exports.aMethod = aMethod
exports.aMethod2 = aMethod2
b.js
javascript
const aMethod = require('./a.js')
console.log(aMethod)
aMethod.aMethod()
aMethod.aMethod2()

导入模块
导入模块时,是通过require方法导入。其用法有一些注意事项:
1.自己定义的模块,在require时,建议写相对路径。
2.js和json导入的模块,可以不写后缀,c/c++编写的node扩展文件也可以不写后缀。对于js和json,是先找js,后找json。所以如果一个路径下同时存在同名的js和json文件,然后省略后缀require,会引入js对应的文件。
3.如果导入其他类型的文件,会按照js文件进行处理。
4.如果导入的路径是一个文件夹,会默认寻找这个文件夹下面的package.json文件中的main属性对应的文件,如果这个文件存在,则会导入这个文件。如果main属性不存在,或者package.json不存在,则会检测index.js和index.json。如果都没有,则会报错。
引入文件夹,且配置了package.json里的main:


如果引入文件,并且找不到package.json里的main和index.js和index.json:

5.导入node.js内置的模块时,直接require模块名即可,不需要填写相对路径。
6.module.exports、exports、require都是CommonJS模块化规范,node.js实现了CommonJS模块化规范。
require导入文件时发生了什么:
当使用require导入自己定义的模块时,会发生什么呢?(该流程只针对于导入自己定义的其他模块,对于内置模块或者第三名模块不适用)
-
将相对路径转为绝对路径,获取模板文件的地址
-
缓存检测(检测该模块是否存在缓存)
-
读取目标文件代码
-
将目标文件代码包裹为一个函数并执行(自执行函数),通过arguments.callee.toString()可以查看自执行函数
javascript
const test = {
a : 1
}
module.exports = test
//对于该文件中的代码,他们其实是被包裹在一个函数中的
//通过arguments.callee可以获得这个函数,
// 然后.toString(),可以打印函数体
console.log(arguments.callee)
console.log(arguments.callee.toString())

-
缓存模块的值
-
返回module.exports的值
伪代码示例:
javascript
function require(file){
//将相对路径转为绝对路径
let absolutePath = Path2D.resolve(__dirname,file)
//缓存检测,检测之前是否已经require过这个文件
//如果require过,直接返回之前的返回值,
//如果没有再执行文件里的代码
if(caches[absolutePath]){ //这里是伪代码写法,表示从缓存中读取
return caches[absolutePath]
}
//没有缓存,读取文件代码并执行
let code = fs.readFileSync(absolutePath).toString()
(
//这里用伪代码模仿js包裹函数
function( exports, require, module, __filename, __dirname ){
...
读取的文件代码
...
}
)(exports, require, module, __filename, __dirname)
//缓存结果
caches[absolutePath] = 模块对象
//返回module.exports
return module.exports
}
CommonJS模块化规范
module.exports exports require都是CommonJS模块化规范中规定的内容,
node.js实现了CommonJS
CommonJS是一个规范,CommonJS与Node.js就像JavaScript与ECMAScript,即CommonJS是模块化代码的规范,而Node.js对该规范做了实现。ECMAScript是标准,JavaScript也是对该标准进行了实现。
包管理工具
包
包,package,是一组特定功能的源码集合。
通俗一点来说,包是可以实现某个功能的源码,下载包之后,就可以直接使用这个包已经实现的功能及方法。
包管理工具
管理包的应用软件。在实际项目中,可能会下载使用非常多的包,使用包管理工具,可以对包进行下载安装、更新、删除、上传等操作,能够快速开发项目、提升开发效率。
包管理工具是通用的概念,不是前端或者后端独有的。
常用的包管理工具
对于前端来说,常用的包管理工具有:
npm
pnpm
cnpm
yarm
npm
npm全称Node Package Manager,即Node包管理工具。
npm是node.js官方内置的包管理工具
npm的安装
在安装node.js时,会自动安装npm,所以一般不需要单独安装npm。
通过npm -v可以查看npm版本。如果想管理npm版本,可以通过nvm来进行。
npm初始化包
npm init
在需要初始化包的目录下敲npm init并按回车,即可初始化工具包。
初始化的意思是说,npm会自动创建一个package.json文件用于对包进行管理和配置。在脚手架项目里,直接敲npm init,不需要配置就可以,但是在空目录下敲npm init,则会进入初始的配置流程:
package name package的名字
version 版本
description 对包进行描述
entry point 入口点
test command 测试命令
git repository 仓库地址
keywords 关键字
author 作者
license 开源证书
给这些值配置好之后,会自动生成对应的配置代码:
敲npm init并填写配置:

然后会生成package.json的初始化配置,并让你确认,确认之后,目录下就会多出对应的package.json文件:

在对package.json进行初始化配置时,需要注意:
-
package name不能使用中文和大写,默认值是文件夹的名称。所以文件夹名称也不能使用中文和大写
-
version 版本号要求使用x.x.x的格式,并且x必须是数字
-
license 证书,证书与MIT证书功能是相同的,证书这里先不展开学习了,之后会单独开一个博文讲证书
-
package.json可以手动创建与修改,也就是说,如果你想全手动创建,也可以不npm init
-
使用 npm init -y或者 npm init --yes可以快速创建package.json,跳过配置环节,生成默认的配置
搜索npm包
有时候,我们想往项目里添加一个功能,但是可能我们由于并不知道有哪些包而感到迷茫,如何搜索npm包呢?
一个方法是在终端或者命令行输入npm s 关键字,或者npm search 关键字。
另一个方法是在相关网址上对npm包进行查询:https://www.npmjs.com/
下载npm包
通过语法 npm install 包名 或者npm i 包名 可以下载包。
在下载包之前,需要对项目文件先进行初始化,保证已经有package.json文件。
当敲完下载命令之后,会对远端的地址进行请求,因此该命令需要联网。
下载包之后,文件目录下会多一个package-lock.json文件,该文件用于固定包的版本信息,它可以使一个包在当前安装和下次安装时是一个版本。
导入npm包
使用require(包名) 导入包
当在package.json安装一个包之后,该包称为package.json的一个依赖。
package.json(我们自己的包A)里安装了别的包B,一般说包B是A的一个依赖包,或者说A依赖B。
使用npm包
按照包的用法说明文档使用包
require导入npm包的流程
上文写了require导入自定义模块的流程,对于使用npm安装并导入的包,当require时会发生什么呢?
- 在当前文件夹下的node_modules中寻找同名的文件夹,如果找到了,就对该文件夹中的内容进行导入。
比如我使用const test = require('test')导入npm包test,
实际上导入的是当前目录下的'./node_modules/test',也就是说下列两种语法是等价的:
javascript
const test = require('test')
const test = require('./node_modules/test')
然后,其实这个说法并不严谨,因为require并不是导入对应文件夹下的全部文件,它导入的是package.json中配置的文件夹下的某个具体的路径。所以其实最后寻找到的是这个路径:
javascript
const test = require('./node_modules/test/配置文件中对应的文件夹下的具体路径')
以uuid为例:

最后引入的其实是,两个引入在本例中是一样的:
javascript
const uuid = require('uuid')
console.log(uuid)
const uuid2 = require('./node_modules/uuid/dist/index')
console.log(uuid2)
- 在上级目录下的node_modules中寻找同名文件夹,直到寻找到根目录。
与直接写相对路径来说不同,写require(包名)时,如果在当前文件夹的node_modules下找不到对应的路径,会往上寻找,直到根目录。