Ajax 知识点
1. 客户端与服务器通信的过程
- 客户端与服务器之间的通信过程,分为请求 - 响应两个步骤。
- 请求的概念:客户端通过网络去找服务器要资源的过程,叫做“请求”
- 响应的概念:服务器把资源通过网络发送给客户端的过程,叫做“响应”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m8q6gyLP-1650621958357)(./images/TongXinGuoCheng.png)]
2. URL地址
-
URL 地址用来表示服务器上每个资源的确切访问路径
-
一个标准的 URL 地址主要由以下 4 个部分构成
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FrElN0Y9-1650621958359)(./images/URL.png)]
- URL 地址 - 协议(protocol)
- 概念:协议是网络协议的简称,用来保证通信的双方能读懂彼此发送过来的消息内容。
- URL 地址 - 主机名(hostname)
- 概念:主机名用来标识互联网中服务器的唯一性。
- 好处:通过主机名,可以保证客户 端在万千的服务器中,找到自己想 访问的那台服务器!
- URL 地址 - 端口号(port)
- 概念:端口号是 0 - 65535 之间的整数,它的主要作用是表示一台计算机中的特定进程所提供的服务。
- 注意:默认是:80端口,可以省略,80端口是网站的默认端口,省略就是80端口
- URL 地址 - 路径(path)
- 概念:路径用来表示资源在服务器上具体的存放位置。
- URL 地址 - 协议(protocol)
3. 什么是 Ajax
- 客户端网页向服务器请求数据的技术
4. Ajax请求数据的5种方式
- 客户端浏览器在请求服务器上的数据时,根据操作性质的不同,可以分为以下 5 种常见的操作
- POST – 向服务器新增数据
- GET – 从服务器获取数据
- DELETE – 删除服务器上的数据
- PUT – 更新服务器上的数据(侧重于完整更新:例如更新用户的完整信息)
- PATCH – 更新服务器上的数据(侧重于部分更新:例如只更新用户的手机号)
5. axios
- axios(发音:艾克C奥斯) 是前端圈最火的、专注于数据请求的库。
- 中文官网地址:http://www.axios-js.com/
- 英文官网地址:https://www.npmjs.com/package/axios
6. GET请求 和 POST请求 有什么区别
- GET 请求只能在 URL 中携带少量的数 据
- POST 请求适合用来提交大量的数 据
- 结论:POST 为了能够提交大量的数据,所以没有把数据拼接到 URL 的末尾;而是放到了独立的“请求体”中。
7. 什么是请求报文和响应报文
- 客户端与服务器通信的过程是基于请求与响应的。其中:
- 请求报文规定了客户端以什么格式把数据发送给服务器
- 响应报文规定了服务器以什么格式把数据响应给客户端
8. http 响应状态码
- 概念:http 响应状态码(Status Code)由三位数字组成,用来标识响应成功与否的状态。
- 作用:客户端浏览器根据响应状态码,即可判断出这次 http 请求是成功还是失败了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cwlCLoIx-1650621958365)(./images/http响应状态码.png)]
-
常见 http 状态码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pVKCvx9H-1650621958367)(./images/常见http状态码.png)]
9. 接口的概念
- 使用 Ajax 请求数据时,被请求的 URL 地址,就叫做数据接口(简称:接口或 API 接口)。
- 例如
- http://www.liulongbin.top:3009/api/getbooks 获取图书列表的接口(GET 请求)
- http://www.liulongbin.top:3009/api/addbook 添加图书的接口(POST 请求)
9.1 接口文档
-
接口文档就是接口的使用说明书,它是我们调用接口的依据。
-
请参考一个现成的接口文档
- https://www.showdoc.com.cn/ajaxapi?page_id=3753563065735122
9.2 接口测试工具
- 测试工具:Postman
- 下载地址::https://www.postman.com/downloads/
10. 表单的三部分
- 网页中采集数据的表单由三个部分组成,分别是:表单标签、表单域、表单按钮。
- HTML 的
<form>
就是表单标签,它是一个“容器”,用来将页面上指定的区域划定为表单区域: - 表单域提供了采集用户信息的渠道,常见的表单域有:input、textarea、select 等。
- 注意:每个表单域必须包含 name 属性,否则用户填写的信息无法被采集到!
- 当表单数据填写完毕后,用户点击表单按钮,会触发表单的提交操作,从而把采集到的数据提交给服务器。
- 注意:
- type=“submit” 表示提交按钮的意思
- type 属性的默认值就是 submit,因此 type=“submit” 可以省略不写
- 注意:
11. 同源策略&跨域
-
什么是同源:
指的是两个url地址具有相同的协议、主机名、端口号
-
什么是跨域:
同源指的是两个 URL 的协议、主机名、端口号完全一致,反之,则是跨域。
-
什么是同源策略:
是浏览器提供的一个安全功能
浏览器的同源策略规定:不允许非同源的 URL 之间进行资源的交互。
Ajax 各种语法
1. axios
的基本使用
url
: 地址
method
: 请求方式,不写默认是GET
axios
(发音:艾克C奥斯) 是前端圈最火的、专注于数据请求的库。- 中文官网地址:http://www.axios-js.com/
- 英文官网地址:https://www.npmjs.com/package/axios
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>axios的基本使用</title>
<!-- 1. 引入 axios.js 文件 -->
<script src="./lib/axios.js"></script>
</head>
<body>
<script>
// 2. 调用 axios
// 调用后就会发起请求
axios({
// 1. URL 地址
url: ' http://www.liulongbin.top:3009/api/getbooks',
// 2. method 请求方式,不写默认是 GET
method: 'GET'
}).then((res) => {
// 在 then 回调中获取数据,回调函数的参数就是我们要获取的数据
console.log(res);
})
</script>
</body>
</html>
2. 参数 - params
语法:
params: {id: 1}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./lib/axios.js"></script>
</head>
<body>
<script>
axios({
method: 'GET',
// 查询参数的本质形式
url: ' http://www.liulongbin.top:3009/api/getbooks',
// url 后面拼接 ? 参数名=参数值&参数名=参数值
// url: ' http://www.liulongbin.top:3009/api/getbooks?id=1',
// params 指定查询参数
params: {
// 参数
id: 1
}
}).then((res) => {
// res 从服务器获取到的数据
console.log(res);
})
</script>
</body>
</html>
3. url编码
encodeURI() 编码
decodeURI() 解码
<script>
// 在绝大部分情况下是不需要手动的进行编码的转换,因为浏览器会自动的将中文等特殊字符进行转换
// 记住浏览器会自动进行url编码转码
// encodeURI() 编码
// 将中文转换成utf8编码
console.log( encodeURI('西游记') ) // %E8%A5%BF%E6%B8%B8%E8%AE%B0
// decodeURI() 解码
// 将编码转换成中文
console.log(decodeURI('%E8%A5%BF%E6%B8%B8%E8%AE%B0'))// 西游记
</script>
4. 套壳后的结果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>套壳后的结果</title>
<script src="./lib/axios.js"></script>
</head>
<body>
<script>
axios({
url: 'http://www.liulongbin.top:3009/api/getbooks',
method: 'GET',
params: {
bookname: '西游记'
}
}).then(({ data:res }) => {
// res 是 axios 把服务器返回的数据进行套壳后的结果
// 服务器的数据在 res 的 data 中
// 解构赋值可以解决使用数据啰嗦问题
// 1. 参数必须有括号 () => {}
// 2. 在括号种声明花括号 ({}) => {}
// 3. 在花括号中声明你要取出来使用的属性名 ({ data })
// 4. 如果需要把属性更改成别名在属性名后面添加 :别名 ({ data:res })
console.log(res.data)
})
</script>
</body>
</html>
5. 使用axios发起POST请求
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>使用axios发起POST请求</title>
<script src="./lib/axios.js"></script>
</head>
<body>
<script>
// 发起一个 POST 请求,添加数据
axios({
url: 'http://www.liulongbin.top:3009/api/addbook',
method: 'POST',
// 提交要添加的(参数)
// POST 请求的参数要放在 data 对象中
data: {
// 以下参数都是后端告诉我们的
// 图书名
bookname: '哈喽哈喽',
// 作者名
author: 'XXX',
// 出版社
publisher: 'XXX'
}
}).then(({ data }) => {
console.log(data)
})
</script>
</body>
</html>
6. form
表单
表单域:用来收集信息,一定要有
name
属性,name
的值就是 参数名表单按钮:用于提交数据的按钮
type
默认是submit
,可以省略不写,不能写别的
<!-- 表单标签 -->
<form action="">
<!-- 表单域:用来收集信息,一定要有 name 属性, name 的值就是 参数名 -->
<input type="text" name="username">
<input type="password" name="password">
<!-- 表单按钮:用于提交数据的按钮 -->
<!-- type 默认是 submit,可以省略不写,不能写别的 -->
<!-- <input type="submit" value="提交"> -->
<button type="submit">提交</button>
</form>
6.1 表单 GET
方式提交
action
: 接口的url
地址 把表单采集到的数据,提交到哪个接口中
method
:GET
或POST
数据的提交方式(默认值为GET
)
enctype
:application/x-www-form-urlencoded
– 数据的编码格式。具体指的是:
multipart/form-data
把表单数据提交给服务器之前,如何对将要提交的数据进行编码
text/plain
(很少用) (默认值application/x-www-form-urlencoded
)注意:
enctype
属性只能搭配POST
提交方式一起使用;如果是GET
提交,则enctype
没有意义!
<!-- 使用 form 表单做 GET 方式的提交 -->
<!-- 指定接口地址和请求 -->
<form action="http://www.liulongbin.top:3009/api/form" method="GET">
<div>
<span>用户名:</span>
<input type="text" name="username">
</div>
<div>
<span>密码:</span>
<input type="password" name="password">
</div>
<button type="submit">提交</button>
</form>
6.2 表单 POST
方式提交
<!-- 使用 form 表单做 POST 方式的提交 -->
<!-- 指定接口地址和请求 -->
<!-- enctype 默认 为application/x-www-form-urlencoded,所以一般可以省略不写 -->
<form action="http://www.liulongbin.top:3009/api/form" method="POST" enctype="application/x-www-form-urlencoded">
<div>
<span>用户名:</span>
<input type="text" name="username">
</div>
<div>
<span>密码:</span>
<input type="password" name="password">
</div>
<button type="submit">提交</button>
</form>
6.3 enctype
属性的区别
enctype
属性的作用:把请求体里面的参数进行编码,GET
没有请求体,在发送GET
请求时设置该属性没有意义功能:约定参数格式
application/x-www-form-urlencoded
最常用,参数都是文字、数字、布尔,不写默认就是该值
multupart/form-data
上传文件text/plain 几乎不用,纯文本
6.4 结合from
和ajax
from只用来收集数据
ajax
负责提交
submit
提交事件 阻止默认行为e.preventDefault()
7. axios请求方法的别名
GET
的请求方法的别名语法:
axios.get()
第一个参数,必填,url地址
第二个参数,选填,对象,对象中设置params,参数
POST
请求方法的别名第一个参数,必填,url地址
第二个参数,选填,直接就是参数对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>axios请求方法的别名</title>
</head>
<body>
<script src="./lib/axios.js"></script>
<script>
// 1. GET的请求方法的别名
// 语法:axios.get()
// 第一个参数,必填,url地址
// 第二个参数,选填,对象,对象中设置params,参数
// 1.1 没有传参
axios.get('http://www.liulongbin.top:3009/api/get').then(({data}) => {
console.log(data);
})
// 1.2 传参
axios.get('http://www.liulongbin.top:3009/api/get',{
params: {
name: 'hh',
age: 99
}
}).then(({data}) => {
console.log(data);
})
// 2. POST 请求方式
// 第一个参数,必填,url地址
// 第二个参数,选填,直接就是参数对象
// 2.1 没有参数
axios.post('http://www.liulongbin.top:3009/api/post').then(({data}) => {
console.log(data);
})
// 2.1 传参
axios.post('http://www.liulongbin.top:3009/api/post',{
name: 'HiHi',
age: 24
}).then(({data}) => {
console.log(data);
})
</script>
</body>
</html>
8. 设置请求的全局根路径
axios.defaults.baseURL = '根路径'
<script src="./lib/axios.js"></script>
<script>
// 设置全局请求根路径
axios.defaults.baseURL = 'http://www.liulongbin.top:3006'
// 设置好全局根路径后,后续的请求就不用在添加根路径
axios.get('/api/get').then(res => {
console.log(res);
})
</script>
9. 拦截器
什么是拦截器
拦截器(interceptors)用来全局拦截 axios 的每一次请求与响应。
好处:可以把每个请求中,某些重复性的业务代码封装到拦截器中,提高代码的复用性。
<script src="./lib/axios.js"></script>
<script>
// 什么是拦截器
// 拦截器(interceptors)用来全局拦截 axios 的每一次请求与响应。
// 好处:可以把每个请求中,某些重复性的业务代码封装到拦截器中,提高代码的复用性。
// 1. axios拦截器可以拦截什么?
// 拦截axios每一次的请求和响应
// 2. 拦截器的好处是什么?
// 可以封装请求和响应中重复的业务代码
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
// 打开弹窗
loading.style.display = 'block'
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 对响应数据做点什么
// 关闭弹窗
loading.style.display = 'none'
return response;
}, function (error) {
// 对响应错误做点什么
// 失败也需要关闭弹窗
loading.style.display = 'none'
return Promise.reject(error);
});
const get = document.querySelector('#get')
const post = document.querySelector('#post')
const loading = document.querySelector('#loading-box')
get.addEventListener('click', function() {
// 请求打开弹窗
// loading.style.display = 'block'
axios.get('http://www.liulongbin.top:3009/api/get').then(({data}) => {
// 请求关闭弹窗
// loading.style.display = 'none'
console.log(data);
})
})
post.addEventListener('click', function() {
// 请求打开弹窗
// loading.style.display = 'block'
axios.post('http://www.liulongbin.top:3009/api/post').then(({data}) => {
// 请求关闭弹窗
// loading.style.display = 'none'
console.log(data);
})
})
</script>
10. 使用FormData
FormData
概念:
FormData
是浏览器提供的一个 WebAPI,它以键值对的方式存储数据。作用:
FormData
配合 Ajax 技术,能够向服务器发送multipart/form-data
格式的请求体数据。典型应用场景:FormData + Ajax 技术实现文件上传的功能。
<script src="./lib/axios.js"></script>
<script>
// FormData
// 概念:FormData 是浏览器提供的一个 WebAPI,它以键值对的方式存储数据。
// 作用:FormData 配合 Ajax 技术,能够向服务器发送 multipart/form-data 格式的请求体数据。
// 典型应用场景:FormData + Ajax 技术实现文件上传的功能。
const fd = new FormData()
fd.append('username', '张三')
fd.append('age', 20)
// 无法直接用log查看
// console.log(fd)
// 1. fd.get 方法接收数据名作为参数,作用是获取与数据名对应值
console.log(fd.get('username'))
// 2.fd.delete 方式接收数据名作为参数,作用删除数据名对应的数据
fd.delete('username')
console.log(fd.get('username'))
// 3.forEach()
fd.forEach((value, key) => {
console.log(key + ':' + value);
})
</script>
11. FormData
结合ajax发送数据
<script src="./lib/axios.js"></script>
<script>
// 准备 FormData 数据
const fd = new FormData()
fd.append('name', 'Hii')
fd.append('age', '24')
// 使用 ajax 发送请求
axios.post('http://www.liulongbin.top:3009/api/formdata', fd).then(({data}) => {
console.log(data);
})
</script>
12. XMLHttpRequest
- 是浏览器内置的一个构造函数
- 作用:基于
new
出来的XMLHttpRequest
实例对象,可以发起 Ajax 的请求。
12.1 xhr的基本使用
创建
XMLHttpRequest
对象 – readyState 为 0
const xhr = new XMLHttpRequest()
调用
open
方法,设置请求方式和请求地址 – readyState 为 1第一个参数:请求方式
第二个参数:请求的地址
xhr.open('请求方式', '请求地址')
调用
send
方法,发起请求 – readyState 为 2
xhr.send()
- readyState 为 3,表示数据正在传输的过程中
监听事件(两种形式),获取服务端返回的数据
load
事件是后台返回数据全部加载完毕的事件readyState 为 4,表示传输完毕
// 1. 创建 XMLHttpRequest 对象
const xhr = new XMLHttpRequest()
// readyState 为 0
// 2. 调用 open 方法,设置请求方式和请求地址
// 第一个参数:请求方式
// 第二个参数:请求的地址
xhr.open('get', 'http://www.liulongbin.top:3009/api/get')
// readyState 为 1
// 3. 调用 send 方法,发起请求
xhr.send()
// readyState 为 2
// readyState 为 3,表示数据正在传输的过程中
// 4. 监听事件(两种形式),获取服务端返回的数据
// 第一种形式
// load 事件是后台返回数据全部加载完毕的事件
xhr.addEventListener('load', function() {
// 获取服务器的返回结果
console.log(xhr.response)
})
// 第二种形式
xhr.addEventListener('readystatechange', function() {
// readyState 为 4,表示传输完毕
if ( xhr.readyState === 4 ) {
// 传输完成,可以获取数据了
console.log(xhr.response)
}
})
12.2 使用xhr发起get
请求
在后面直接拼接要传的参数
<script>
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://www.liulongbin.top:3009/api/get?name=张三&age=18')
xhr.send()
xhr.addEventListener('load', function() {
console.log(xhr.response);
})
</script>
12.3 使用xhr发起post
请求
请求体参数应放在
send
参数里设置请参数的编码格式
2.1 设置请求头
xhr.setRequestHeader('设置请求头', '编码格式')
- 第一个参数为设置请求头(固定单词)
- 第二个参数为设置编码格式
<script>
const xhr = new XMLHttpRequest()
// 发起 post 请求,open的第一个参数要设置成post
// 在 url 后面的参数叫做查询参数
xhr.open('POST', 'http://www.liulongbin.top:3009/api/post')
// 请求体参数应放在send参数里
// 设置请参数的编码格式
// 设置请求头
// 第一个参数为设置请求头(固定单词)
// 第二个参数为设置编码格式
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// send 字符串
xhr.send('name=张三&age=18')
xhr.addEventListener('load', function() {
console.log(xhr.response);
})
</script>
13. 数据交换格式
数据交换格式:
数据交换格式,就是服务器端与客户端之间数据传输的格式。
两种数据交换格式:
1.
XML
(很少用) 2.
JSON
(主流)
14. JSON
字符串
JSON
格式 用字符串表示对象或数组 就是
JSON
格式规定:
- key 必须使用双引号包裹
- value 必须是 字符串(必须用双引号包裹)、数字、布尔值、
null
、数组、对象类型
JSON
操作:
- 序列化:把真实的数据转换为字符串的过程
- 反序列化:把字符串转换为真实数据的过程
// 数据交换格式
// 数据交换格式,就是服务器端与客户端之间数据传输的格式。
// 两种数据交换格式:
// 1. XML(很少用)
// 2. JSON(主流)
// JSON 格式
// 用字符串表示对象或数组 就是 JSON
// 格式规定:
// 1. key 必须使用双引号包裹
// 2. value 必须是 字符串(必须用双引号包裹)、数字、布尔值、null、数组、对象类型
// JSON 格式写法
const data = '{"name":"张三","age":18,"isOver":false}'
// 数组中只能放 字符串(必须用双引号包裹)、数字、布尔值、null、数组、对象(符合json对象字符串的规则)
const arr = '["abc",18,{"name":"zs"}]'
// JSON 操作
// 1. 序列化:把真实的数据转换为字符串的过程
// 2. 反序列化:把字符串转换为真实数据的过程
// 序列化:把真实数据转换为字符串的过程
// 将对象或数组转换成 JSON 字符串
console.log( JSON.stringify({name: "张三", age: 20}) )
// 反序列化:把字符串转换为真实数据的过程
// 将 JSON 转换成可以操作的对象或数组
console.log( JSON.parse(data) )
15. 在 ajax 中使用 JSON
发送数据时可以发送
json
一定要设置
json
格式的请求头
xhr.setRequestHeader('Content-Type', 'application/json')
后端给我们返回的是 JSON 不好操作
使用反序列化,将 json 转换成可以操作的对象
console.log( JSON.parse(xhr.response) )
const obj = {
name: "张三",
age: 18
}
const xhr = new XMLHttpRequest()
xhr.open('POST', 'http://www.liulongbin.top:3009/api/post')
// 发送数据时可以发送 json
// 1. 一定要设置 json 格式的请求头
xhr.setRequestHeader('Content-Type', 'application/json')
// 为了操作方便,先创建对象,使用序列化将对象转换成json
xhr.send( JSON.stringify(obj) )
xhr.addEventListener('load', function() {
// 后端给我们返回的是 JSON 不好操作
// 使用反序列化,将 json 转换成可以操作的对象
console.log( JSON.parse(xhr.response) )
})
16. 案例 - 封装自己的 ajax
js 文件
html 文件
- js 文件
function ajax(options) {
// 处理 params 参数
// 先判断调用者是否传递了 params 参数对象
if (options.params) {
// 准备数组
const arr = []
// 遍历 params 对象
for(let key in options.params) {
// 按照 key = value 的格式保存到数组中
arr.push(`${key}=${options.params[key]}`)
}
// 判断数组中是否有内容,判断 params 是不是空
if(arr.length > 0) {
options.url += '?' + arr.join('&')
}
}
// 1. 创建 xhr
const xhr = new XMLHttpRequest()
// 2. 调用 open 设置请求方式和请求地址,通过传递过来的参数设置
xhr.open(options.method, options.url)
// 处理 data 的参数
// POST 的时候才需要处理 data
if ( options.method.toUpperCase() === 'POST' && options.data ) {
// 1. 如果 options.data 是一个对象,application/json
if ( typeof options.data === 'object' && !(options.data instanceof FormData) ) {
// 设置编码格式
xhr.setRequestHeader('Content-Type', 'application/json')
// 发送数据
xhr.send( JSON.stringify(options.data) )
}
// 2. 如果 options.data 是一个字符串,application/x-www-form-urlencoded
if ( typeof options.data === 'string' ) {
// 设置编码格式
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 发送数据
xhr.send(options.data)
}
// 3. 如果 options.data 是一个FormData
if ( options.data instanceof FormData ) {
// 直接发给后台
xhr.send(options.data)
}
} else {
// 3. 调用 send
xhr.send()
}
// 4. 监听完成事件
xhr.addEventListener('load', function() {
// 把服务器返回的数据传给函数的调用者,调用 success 回调
options.success( JSON.parse(xhr.response) )
})
}
- html 文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>封装自己的ajax</title>
</head>
<body>
<script src="./js/myAjax.js"></script>
<script>
let fd = new FormData()
fd.append('name', 'zs')
fd.append('age', 18)
ajax({
method: 'POST',
url: 'http://www.liulongbin.top:3009/api/post',
// data: fd,
// data: {name:'zs', age:18},
data: 'name=zs&age=18',
success: function (res) {
console.log(res);
}
})
</script>
</body>
</html>
17. 防抖(debounce)
用来优化 ajax 的
频繁触发某个操作时,只执行最后一次
过程:
- 在事件外面声明定时器 id 变量
- 在每一次事件触发时都干掉上一次的 timer
- 定义一个延迟定时器,在定时器内执行事件的逻辑,保存定时器 id
<script>
// 需求:输入时打印输入框的文字
// 1. 在事件外面声明定时器 id 变量
let timer = null
let inp = document.querySelector('.ipt')
inp.addEventListener('input', function() {
// 用 console.log 来替代 ajax 请求
// 防抖:只打印输入完成的全部内容,之前输入的不做处理 - 防抖
// 2. 在每一次事件触发时都干掉上一次的 timer
clearTimeout(timer)
// 3. 定义一个延迟定时器,在定时器内执行事件的逻辑,保存定时器 id
timer = setTimeout(() => {
console.log(inp.value)
}, 500)
})
</script>
18. 节流(throttle)
- 节流阀,标识符,标记当前是否有一个定时器
- 在事件中判断是否有一个定时器
- 在定时任务纲要创建时,把节流阀修改状态
- 创建定时器 – 要执行的逻辑
- 把节流阀修改回初始状态
<script>
// 需求每点赞一次就像后台发送一次请求
const box = document.querySelector('#box')
// 1. 节流阀,标识符,标记当前是否有一个定时器
let isOk = false
box.addEventListener('click',function() {
// 2. 在事件中判断是否有一个定时器
// 如果有就 return,后续代码不再执行,如果没有就继续执行
if (isOk) return
// 3. 在定时任务纲要创建时,把节流阀修改状态
isOk = true
// 4. 创建定时器
setTimeout(() => {
// 要执行的逻辑
console.log('你点击了1次');
// 5. 把节流阀修改回初始状态
isOk = false
},3000)
})
</script>
Git 总结
1. 什么是 Git
- Git 是一个开源的分布式版本控制系统,是目前世界上最先进、最流行的版本控制系统。
2. Git 中的三个区域
- 分别是工作区、暂存区、Git仓库
- 工作区:正在写的项目文件夹区域
- 暂存区:临时存放已经完成的文件区域
- Git仓库:把最终存放的文件区域
3. Git 中的三个状态
- 本别是已修改、已暂存、已提交
- 已修改:表示修改了文件,但还没 将修改的结果放到暂存区
- 已暂存:表示对已修改文件的当前 版本做了标记,使之包含 在下次提交的列表中
- 已提交:表示文件已经安全地保存 在本地的 Git 仓库中
4. 本的 Git 工作流程
- 在工作区中修改文件
- 将你想要下次提交的更改进行暂存
- 提交更新,找到暂存区的文件,将快照永久性 存储到 Git 仓库
5. 安装并配置 Git
5.1 在 Windows 中下载并安装 Git
在开始使用 Git 管理项目的版本之前,需要将它安装到计算机上。可以使用浏览器访问如下的网址,根据自 己的操作系统,选择下载对应的 Git 安装包: https://git-scm.com/downloads
5.2 配置用户信息
-安装完 Git 之后,要做的第一件事就是设置自己的用户名和邮件地址。因为通过 Git 对项目进行版本管理的 时候,Git 需要使用这些基本信息,来记录是谁对项目进行了操作:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8J2MNmTC-1650621958370)(./images/git配置.png)]
5.3 Git 的全局配置文件
通过 git config --global user.name 和 git config --global user.email 配置的用户名和邮箱地址,会被写 入到 C:/Users/用户名文件夹/.gitconfig 文件中。这个文件是 Git 的全局配置文件,配置一次即可永久生效 。 可以使用记事本打开此文件,从而查看自己曾经对 Git 做了哪些全局性的配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sQ37yDkc-1650621958371)(./images/git5.3.png)]
5.4 检查配置信息
除了使用记事本查看全局的配置信息之外,还可以运行如下的终端命令,快速的查看 Git 的全局配置信息:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WDKpSFGV-1650621958372)(./images/git5.4.png)]
6. Git 基本操作
6.1 获取Git仓库 - git init
注:每个项目用一次
git init
将本地的目录初始化为Git仓库
- 将本地的目录初始化为Git仓库(本地已有或刚创建项目时)
- 打开项目文件夹
- 在该文件夹中右键->Git Bash Here 打开Git命令
- 在命令行输入
git init
- 从远程服务器克隆Git仓库(项目要保存到网上或者公司的服务器已有项目)
6.2 查看文件状态 - git status
git status
**【推荐】**查看文件状态
git status -s
以精简方式查看文件状态,这个是下面的简写
git status --short
以精简方式查看文件状态
git status
# 以精简方式查看文件状态,下面两个命令是一回事,第一个是第二个的简写
git status -s
git status --short
# 未跟踪文件前面有红色的 ?? 标记,
6.3 将工作区的代码提交到暂存区 - git add .
注:每一个新文件或每对一个文件进行修改后
git add 文件名
将工作区某一个文件的代码提交到暂存区
git add .
**【推荐】**将工作区的所有文件的代码提交到暂存区
git add 文件名
# 下面这条是常用名,将文件夹内所有的文件(新建的文件或已修改的文件)都添加到暂存区
git add .
6.4 将暂存区的文件提交到Git仓库 - git commit -m "本次提交的注释消息"
建议:每完成一个功能提交一次
git commit -m "本次提交的注释消息"
git commit -m "本次提交的注释信息"
6.5 流程
# 1. 在项目文件夹中初始化git仓库,一个项目一次
git init
# 2. 将新建文件或修改后的文件提交到暂存区
git add .
# 3. 将暂存区的文件提交到git仓库
git commit -m "提交的注释消息"
# 2-3步是频繁执行,只要有新内容提交,就需要执行
7. Git 忽略文件
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 在这种情况下,我们 可以创建一个名为 .gitignore 的配置文件,列出要忽略的文件的匹配模式。
- 文件 .gitignore 的格式规范如下:
- 以 # 开头的是注释
- 以 / 结尾的是目录
- 以 / 开头防止递归
- 以 ! 开头表示取反
- 可以使用 glob 模式进行文件和文件夹的匹配(glob 指简化了的正则表达式)
- 所谓的 glob 模式是指简化了的正则表达式:
- 星号 * 匹配零个或多个任意字符
- [abc] 匹配任何一个列在方括号中的字符 (此案例匹配一个 a 或匹配一个 b 或匹配一个 c)
- 问号 ? 只匹配一个任意字符
- 在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹 配所有 0 到 9 的数字)
- 两个星号 ** 表示匹配任意中间目录(比如 a/**/z 可以匹配 a/z 、 a/b/z 或 a/b/c/z 等)
- 所谓的 glob 模式是指简化了的正则表达式:
8. 远程创建仓库连接
-
创建的仓库(创建时,最后有复选框,勾选和不勾选会导致了两种关联方式)
-
不勾选复选框(创建了空仓库)
- 在本地创建项目文件夹
git init
- 保证文件夹内有文件(建议新建一个README.md文件,这个是网页首页显示的)
git add .
git commit -m "备注"
git remota add origin 仓库地址
git push -u origin "master"
(-u origin master设置默认推送)
-
勾选复选框(创建非空仓库,或者到单位给一个非空的项目)
- 进入到要存放的项目文件夹
- 在文件夹上打开命令行
git clone 仓库地址(克隆/下载复制来的地址)
- 不需要做任何配置,直接进行后续的开发
-
开发
-
每完成一个功能(页面)
-
git add .
-
git commit -m "备注"
-
git push
234三个步骤重复执行
-
-
9. Git 分支
- 分支概念:
- 分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努 力学习SVN。
- 如果两个平行宇宙互不干扰,那对现在的你也没啥影响。
- 不过,在某个时间点,两个平行宇宙合并了,结果,你既学会了Git又学会了SVN!
- 分支在实际开发中的作用
- 在进行多人协作开发的时候,为了防止互相干扰,提高协同开发的体验,建议每个开发者都基于分支进行项 目功能的开发
- master 主分支
- 在初始化本地 Git 仓库的时候,Git 默认已经帮我们创建了一个名字叫做 master 的分支。通常我们把这个 master 分支叫做主分支。
- 作用:
- 用来保存和记录整个项目已完成的功能代码。因此,不允许程序员直接在 master 分支上修改代码,因为这样做的风险太高,容易导致整个项目崩溃。
- 功能分支
- 功能分支指的是专门用来开发新功能的分支,它是临时从 master 主分支上分叉出来的,当新功能开发且测 试完毕后,最终需要合并到 master 主分支上。
10. Git 本地分支操作
-
查看分支列表
# 使用如下的命令,可以查看当前 Git 仓库中所有的分支列表: # 注意:分支名字前面的 * 号表示当前所处的分支。 git branch
-
创建新分支
# 使用如下的命令,可以基于当前分支,创建一个新的分支,此时,新分支中的代码和当前分支完全一样: # 基于主分支上来创建的 复制主分支所有内容到新分支 git branch 分支名
-
切换分支
# 使用如下的命令,可以切换到指定的分支上进行开发: git checkout 分支名
-
合并分支
# 切换到主分支 git checkout 主分支名 # 把选择的功能分支合并到主分支上 git merge 功能分支名
-
分支的快速创建和切换
# 使用如下的命令,可以创建指定名称的新分支,并立即切换到新分支上:
get checkout -b 分支名称
- 删除本地分支
# 当把功能分支的代码合并到 master 主分支上以后,就可以使用如下的命令,删除对应的功能分支:
get branch -d 分支名称
-
遇到冲突时的分支合并
- 发生冲突后手动选择留下哪一个或者都留下
11. Git 远程分支操作
-
如果是第一次将本地分支推送到远程仓库,需要运行如下的命令:
例如:
# -u:把本地分支和远程分支进行关联,远程的 origin 这个仓库,本地的时 list 仓库和远程的 li 分支进行关联 git push -u origin list:li 注:后续在本地list分支推送到远程li分支的时候只需要 git push 就好了,不用加 -u 后的代码 #-u:把本地分支和远程分支进行关联,远程的 origin 这个仓库,本地的时 list 仓库和远程的 list 分支进行关联 git push -u origin list
-
查看远程仓库中所有的分支列表
git remote show 远程仓库名称
-
拉取远程分支的最新的代码
# 从远程仓库,拉取当前分支最新的代码,保持本地分支代码和远程分支代码一致 git pull