From f74e59c7d90e6954a3162ac96789415e70978d58 Mon Sep 17 00:00:00 2001 From: yuluo <2216847528@qq.com> Date: Mon, 29 Apr 2024 15:25:55 +0800 Subject: [PATCH] add ajax content --- docs/.vitepress/config.mts | 3 +- ...37\350\203\275\346\240\207\347\255\276.md" | 11 + docs/front-end/05-Node.js/07-express.md | 13 + docs/front-end/07-ajax/01-ajax.md | 706 ++++++++++++++++++ docs/front-end/07-ajax/index.md | 1 + 5 files changed, 733 insertions(+), 1 deletion(-) create mode 100644 docs/front-end/07-ajax/01-ajax.md create mode 100644 docs/front-end/07-ajax/index.md diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 60e56b34..0b780880 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -53,7 +53,7 @@ export default defineConfig({ }, { text: 'Ajax', - link: '/front-end/' + link: '/front-end/07-ajax/' }, { text: 'Promise', @@ -162,6 +162,7 @@ sidebar: { "/front-end/04-ES6/": set_sidebar("/docs/front-end/04-ES6/"), "/front-end/05-Node.js/": set_sidebar("/docs/front-end/05-Node.js/"), "/front-end/06-mongoDB/": set_sidebar("/docs/front-end/06-mongoDB/"), + "/front-end/07-ajax/": set_sidebar("/docs/front-end/07-ajax/"), "/blogs/01-technology/": set_sidebar("/docs/blogs/01-technology/"), "/devops/git/": set_sidebar("/docs/devops/git/"), }, diff --git "a/docs/front-end/01-HTML5CSS3/02-HTML\345\212\237\350\203\275\346\240\207\347\255\276.md" "b/docs/front-end/01-HTML5CSS3/02-HTML\345\212\237\350\203\275\346\240\207\347\255\276.md" index 03a39a5d..680187e5 100644 --- "a/docs/front-end/01-HTML5CSS3/02-HTML\345\212\237\350\203\275\346\240\207\347\255\276.md" +++ "b/docs/front-end/01-HTML5CSS3/02-HTML\345\212\237\350\203\275\346\240\207\347\255\276.md" @@ -525,6 +525,17 @@ colspan: 设置所跨列数 ``` +当类型为file时为上传文件 + +```html +
+ + +
+``` + + + #### 密码输入框 ```html diff --git a/docs/front-end/05-Node.js/07-express.md b/docs/front-end/05-Node.js/07-express.md index 425217f7..aae6ff0e 100644 --- a/docs/front-end/05-Node.js/07-express.md +++ b/docs/front-end/05-Node.js/07-express.md @@ -335,6 +335,8 @@ body-parser包中间件 可以把req.body中的数据解析转为对象 express-generator包 自带body-parser可以把req.body中的数据自动解析为对象 mongoose包自带body-parser可以把req.body中的数据自动解析为对象 +表单发送的content-type类型是application/x-www-form-urlencoded解析为对象 +默认发送的content-type类型是text/plain源格式还是字符串。 ``` ```js @@ -525,3 +527,14 @@ data.json ] ``` +设置响应体为json格式 + +```json +// 响应一个json数据 +res.json({ + code: '1001', + msg: '读取失败~~', + data: null +}); +``` + diff --git a/docs/front-end/07-ajax/01-ajax.md b/docs/front-end/07-ajax/01-ajax.md new file mode 100644 index 00000000..178c4a2b --- /dev/null +++ b/docs/front-end/07-ajax/01-ajax.md @@ -0,0 +1,706 @@ +# Ajax + + Ajax 全称为 Asynchronous Javascript And XML,就是异步的 JavaScrript 和 XML。 + +# 原生 Ajax + +## 基本使用流程 + +```js +// 第一步 创建 XMLHttpRequest 对象 是XML的dom对象,HTML是XML的子集 +const xhr = new XMLHttpRequest(); + +// 第二步 监听响应成功的事件 +xhr.onload = () => { + console.log('成功接收到后端的响应!'); + box.innerHTML += xhr.responseText + '
'; +}; +// 监听响应超时事件 +xhr.ontimeout = function(){ + alert('响应超时!'); +} + +// 监听按钮点击事件 +xhr.onclick = function(){ + // 请求初始化 + + // 发送请求 +} + +// 第三步 请求初始化 +/* + 第一个参数 请求方式 + 第二个参数 请求URL + 第三个参数 是否异步,默认异步 +*/ +xhr.open('GET', '/getData'); + +// 第四步 发送请求 +/* + 参数可以设置请求体,没有请求可以不设置参数 +*/ +xhr.send(); +``` + +### 发起请求携带数据 + +#### 通过 URL 携带数据 + +> 所有的请求方式都可以通过 URL 携带数据 + +```js +// 定义查询字符串 +const qs = `username=${nameInp.value}&userpwd=${pwdInp.value}`; +// 请求初始化 将携带的数据以查询字符串的形式拼接到 URL 中 +xhr.open('GET', '/addData?'+qs) +// 发送请求 +xhr.send(); +``` + +#### 通过请求体携带数据 + +请求体只能是字符串的格式 + +> POST、PUT 、DELETE等方式可以通过Ajax 发送请求体携带数据 + +```js +// 定义查询字符串 +const qs = `username=${nameInp.value}&userpwd=${pwdInp.value}`; + +// 初始化 +xhr.open('POST', '/addData'); + +// 设置请求头 请求头一定要在 open() 之后,send() 之前设置 +// 通过请求头 Content-type,告知后端请求体的类型 +xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + +// 发送请求,请求体必须是字符串,字符串的格式可以有很多 +xhr.send(qs) +``` + +#### 请求体内容类型 + +text/plain 请求体只要是字符串就可以 + +```js +1. 默认的请求体类型,如果不设置请求头字段 Content-type,默认就是该种类型 +2. 请求体只要是字符串就可以,后端不会做任何处理 +``` + +**application/x-www-form-urlencoded** 要求请求体是查询字符串 + +```js +1. 需要设置请求头 xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); +2. 要求请求体是查询字符串,如 a=100&b=200 +3. 点击提交按钮提交表单(非Ajax),如果 Method 是 Post,默认请求体内容就是 x-www-form-urlencoded +``` + +**application/json** 要求请求体是 json 格式的字符串 + +```js +1. 设置设置请求头 xhr.setRequestHeader('Content-type', 'application/json'); +2. 要求请求体是 json 格式的字符串 +先定义一个对象,然后使用JSON内置对象的JSON.stringify(data)方法将对象转为json格式的字符串 +``` + +**multipart/form-data** + +```js +参考 FormData +后端自动处理为对象格式 +``` + +POST和PUT请求的区别 + +```js +POST为了向数据库添加新数据 +PUT为了向数据库更新数据 +DELETE为了向数据库删除数据 +GET向数据库查询数据 +``` + + + +#### FormData 对象作为请求体 + +```js +1. 请求体(send()的方法的参数)除了是字符串,也可以是 formData 对象 +2. 如果请求体是 FormData 对象,浏览器会自动设置请求头字段 Content-type 为 multipart/form-data +``` + +```js +// 方式一 创建 空的 FormData,再添加数据,可以添加文件数据或者字符串数据 +var fd = new FormData(); +fd.append('message', msgInput.value); +fd.append('content', 'hello ajax'); + +// 方拾二 根据表单元素创建 FormData 会包含表单中所有的信息 +var fd = new FormData(formElement); +``` + +```js +// 点击按钮 发送请求 第一种formData的处理方式 +const btn1 = document.querySelector('#btn1'); +btn1.onclick = () => { + // 创建FormData + const fd = new FormData(); + // 向fd对象添加数据 + fd.append('username', nameInp.value); + fd.append('userpwd', pwdInp.value); + fd.append('mssage', 'hello 高小乐'); + fd.append('avator', avatorInp.files[0]) + + // 请求初始化 + xhr.open('POST', '/upload'); + // 发送请求 fd对象作为参数, 会自动设置请求头字段 Content-type为multipart/form-data + xhr.send(fd); +}; +``` + +#### FormData 对象方法 + +```js +append() 添加数据 第一个参数是key,第二个参数是value +set() 设置数据,有的就修改,没有就添加 +delete() 删除数据 +get() 查询数据 +getAll() +``` + +#### FormData 实现文件上传 + +```js +// 方式一 创建 空的 FormData,再添加数据,可以添加文件数据 +var fd = new FormData(); +// 当input标签的类型为file时,dom对象元素的files方法,可以得到一个fileList[]伪数组,里边存放了图片内容,如果只传一张照片则只需要第一个 +fd.append('avator', avatorInput.files[0]); + + +// 方拾二 根据表单元素创建 FormData 会包含表单中所有的信息 +var fd = new FormData(formElement); +``` + +```javascript +// 点击按钮1 发送请求 第一种formData的处理方式 不使用form表单 使用ajax方式提交 +const btn1 = document.querySelector('#btn1'); +btn1.onclick = () => { + // 创建FormData + const fd = new FormData(); + // 向fd对象添加数据 + fd.append('username', nameInp.value); + fd.append('userpwd', pwdInp.value); + fd.append('mssage', 'hello 高小乐'); + // avatorInp.value只能拿到图片的地址 + fd.append('avator', avatorInp.files[0]) + + // 请求初始化 + xhr.open('POST', '/upload'); + // 发送请求 fd对象作为参数, 会自动设置请求头字段 Content-type为multipart/form-data + xhr.send(fd); +}; + + +// 点击按钮2 发送请求 第二种formData的处理方式 使用form表单 但是阻止默认行为 使用Ajax方式提交 +const btn2 = document.querySelector('#btn2'); +btn2.onclick = () => { + const formBox = document.querySelector('form'); + // 创建FormData 参数是form元素 + // 自动将form元素中的表单控件添加到 formData中 + const fd = new FormData(formBox); + + // 请求初始化 + xhr.open('POST', '/upload'); + // 发送请求 fd对象作为参数, 会自动设置请求头字段 Content-type为multipart/form-data + xhr.send(fd); +}; +``` + +非Ajax上传文件,使用表单上传文件 + +```html +// input标签的类型为file时,可以上传文件 + +

非Ajax 表单上传文件

+ +
+ + +
+``` + + + +## 读取响应报文 + +```js +// 响应行 +xhr.status; // 响应状态码 +xhr.statusText; // 响应状态描述 + +// 响应头 +xhr.getResponseHeader('响应头字段'); // 获取指定字段的响应头的信息 +xhr.getAllResponseHeaders(); // 获取所有的响应头信息 返回一个字符串 + +// 响应体 +xhr.responseText; // 获取响应体体符串 +xhr.response; // 获取响应体字符串,如果响应体是特殊格式的字符串(json),会进行处理 +``` + +## json 格式的数据 + +### 设置 xhr.responseType 属性 + +后端设置响应头,告知浏览器响应体的内容类型是 json 格式 + +```js +Content-type: application/json;charset=utf-8 +``` + +### 客户端处理接收到的 json 数据 + +① 方式一 使用 JSON.parse + +```js +// 监听响应结束的回调函数、 +xhr.onload = function() { + // 将响应体中 json 格式的字符串处理成对象 + var resData = JSON.parse(xhr.responseText); +} +``` + +② 方式二 设置 xhr.responseType 属性 ,通过 xhr.response获取 + +```js +xhr.responseType = 'json'; +xhr.onload = function() { + xhr.response; // 直接得到处理好的对象 +} +``` + +### 客户端设置响应超时 + +方案一 兼容方案 + +```js +// 发送请求 +xhr.send(); + +// 发送请求之后,设置单次定时,如果时间到了还没有接收到响应,中断请求 +setTimeout(function(){ + // 判断如果没有响应结束 + if (xhr.readyState !== 4) { + xhr.abort(); // 中断请求 + alert('请求超时!'); + } +}, 5000); +``` + +方案二 XHR2 方案 + +```js + // 监听响应超时的事件 +xhr.ontimeout = function(){ + alert('响应超时!'); +} + +// 请求初始化 +xhr.open('GET', '/getInfo'); + +// 发送请求之前设置超时时间 +xhr.timeout = 5000; + +// 发送 +xhr.send(); +``` + +### HTTP 进度事件 + +#### 进度相关事件 + +```js +xhr.readystatechange = function(){ + +} +``` + +```js +readystatechange 触发至少 4 次 ,大的事件集合,包含1 2 3 4 过程 +readystate 0 初始值 +readystate 1 请求初始化完成 执行 open(),开始发送请求 +readystate 2 发送请求 执行 send() +readystate 3 开始接收响应 可能触发多次 根据相应体大小 触发多次 +readystate 4. 响应接收完毕 load事件触发 + +readystatechange 拆分出来细分的事件 +readyState readystatechange的状态 +loadstart 开始请求的时候触发,对应此时 readyState 的值是 1和2之间 +load 响应结束的时候触发,对应此时 readyState 的值是 4,请求成功触发 +error 请求失败触发,应用层面的错误也算是请求成功(如 404错误),只有网络错误才算请求失败,请求发不出去 +loadend 响应结束之后触发,不论请求是否成功都会触发 +progress 开始接收响应内容之后,被触发多次,该事件的回调函数可以获取一个 progressEvent 对象 开始接收响应的时候 不停的触发多次,直到接收响应体完毕 + + + + +// 早期没有load事件时 兼容性写法 +if (xhr.readyState === 4) { + // 处理响应体 +} +// 现在的写法 +xhr.onload = function(){ + // 处理响应体 +} +``` + +> **相关事件的触发顺序:** loadstart、progress(可能会触发多次)、 load/error、loadend + +#### ProgressEvent 事件对象 + +progress 事件的回调函数可以获取一个 progressEvent 对象,该对象有如下属性: + +```js +loaded 表示当前已经下载的字节数 +total 表示响应内容的总长度 后端响应头中content-length +``` + +```js +// 开始接收响应的时候 不停的触发多次,直到接收响应体完毕 +xhr.onprogress = event => { + console.log('progress:', event.loaded, event.total); + box.innerHTML = '已下载:' + (event.loaded / event.total * 100).toFixed(2) + '%'; +} +``` + + + +### 异步请求和同步请求 + +**两者区别:** + +```js +1. 异步请求,请求发送之后,其他同步操作继续执行; 当获取响应之后触发回调函数,回调函数进入回调队列等待主线程空闲执行 +2. 同步请求,请求发送之后,其他的同步操作必须等到,响应结束之后才能继续执行 +``` + +**如何发送同步请求:** + +```js +open() 方法的第三个参数是布尔值,true 表示异步请求,false 表示同步请求,默认值是 true。 +``` + +## XMLHttpRequest 对象总结 + +#### ① XHR 对象概述 + +1)XMLHttpRequest 对象简称 **XHR** 对象。 + +2)XMLHttpRequest 对象提供了对 HTTP 协议的完全的访问,包括做出 POST 和 HEAD 请求以及普通的 GET 请求的能力。 + +3)XMLHttpRequest 可以同步或异步地返回 Web 服务器的响应,并且能够以文本或者一个 DOM 文档的形式返回内容。 + +4)尽管名为 XMLHttpRequest,它并不限于和 XML 文档一起使用,它可以接收任何形式的文本文档。 + +#### ② 创建 XHR 对象 + +使用构造函数 XMLHttpRequest 就可以创建一个 XHR 对象。 + +XMLHttpRequest 对象 是XML的dom对象,HTML是XML的子集 + +```js +const xhr = new XMLHttpRequest(); +``` + +注意:在古老的 IE 浏览器中(如:IE6),需要使用其他方式来创建 XHR 对象。 + +```js +// IE5、IE6 +let xhr = new ActiveXObject("Microsoft.XMLHTTP"); +``` + +#### ③ XHR 对象的属性 + +| 属性名 | 含义 | +| ------------ | ------------------------------------------------------------ | +| readyState | 返回一个数字,表示请求的状态:
0 -- UNSET -- XHR对象已创建或已被 abort() 方法重置。
1 -- OPENDED -- `open()` 方法已经被调用。
2 -- HEADERS_RECEIVED -- `send()` 方法已经被调用,并且响应头和响应状态已经可获得。
3 -- LOADING -- 下载中, `responseText` 属性已经包含部分数据。
4 -- DONE -- 所有响应数据接收完毕。 | +| status | 响应状态码,如 404、200 等。 | +| statusText | 响应状态码的文本描述,如 200 对应的是 “OK”。 | +| responseXML | 接收格式为 XML 的响应数据,返回一个 document 对象。 | +| responseText | 获取响应文本,返回一个字符串。是一个字符串类型的响应体。 | +| responseType | 用于设置响应内容的类型 *xhr2* | +| response | 返回的类型取决于 responseType 的设置。 *xhr2* | +| timeout | 设置超时时间。*xhr2* | + +#### ④ XHR 对象的方法 + +| 方法名 | 含义 | +| ----------------------- | ------------------------------------------------------------ | +| open() | 初始化 HTTP 请求,用来指定请求方式和 URL。 `xhr.open(method, url, [async], [user], [password])` | +| send() | 发送 HTTP 请求,参数可以设置请求体,没有请求体无需设置参数。 | +| setRequestHeader() | 设置 HTTP 请求头的值。必须在 `open()` 之后、`send()` 之前调用。 | +| abort() | 如果请求已被发出,则立刻中止请求。 | +| getAllResponseHeaders() | 以字符串形式返回所有的响应头。 | +| getResponseHeader() | 返回指定的响应头。 | + +#### ⑤ XHR 对象的事件 + +| 事件名 | 含义 | +| ---------------- | ------------------------------------------------------------ | +| readystatechange | readyState 属性值发生变化触发该事件。 | +| abort | 请求终止时触发。 | +| error | 请求遇到错误时触发。**注意**,只有发生了网络层级别的异常才会触发此事件。 | +| loadstart | 接收到响应数据时触发。 *xhr2* | +| load | 请求成功完成时触发。*xhr2* | +| loadend | 当请求结束时触发, 无论请求成功 ( `load`) 还是失败 (`abor` 或 `error`)。*xhr2* | +| progress | 当请求接收到更多数据时,周期性地触发。*xhr2* | +| timeout | 在预设时间内没有接收到响应时触发。*xhr2* | + +# 跨域 + +## 同源策略 + +* 同源策略是浏览器的一种安全策略。 +* 同源策略要求 ajax 代码所在的页面URL中的 协议、域名、端口号与 ajax 请求的 URL 中 协议、域名、端口号保持一致 +* 违反同源策略称为跨域, 实现跨域方案: **CORS** **JSONP** + +```js +客户端的请求可以发送到后端,后端也对客户端进行响应,但是客户端(浏览器)对响应进行拒绝 +``` + + + +## CORS 跨域资源共享 + +```js +在服务端进行设置 +添加一个响应头,设置允许的 域名 + +Access-Control-Allow-Origin: http://localhost:8080 +# 允许前面页面的域名是http://localhost:8080,才能跨域 + +Access-Control-Allow-Origin:* +# 允许所有的域名都可以跨域 +``` + +**1) CORS是什么?** + +CORS(Cross-Origin Resource Sharing),跨域资源共享。CORS是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持 GET、POST 等所有的请求方式。 + +**2)CORS怎么工作的?** + +CORS 后端是通过设置一个响应头 `Access-Control-Allow-Origin` 来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行。 + +后端侧设置 + +```js +// 1. 同源策略 ----------------------------------------------------------------------- +// 同源策略 +app.get('/page01', (req, res) => { + res.sendFile(path.join(__dirname, '01-CORS.html')); +}); +// 接收 ajax 请求 +app.get('/getdata01', (req, res) => { + // 允许单个域名跨域请求 + // res.set('Access-Control-Allow-Origin', 'http://localhost:8080'); + // res.set('Access-Control-Allow-Origin', 'http://192.168.2.231:8080'); + + // 允许多个域名跨域请求 + // const allowOrigins = ['http://localhost:8080', 'http://192.168.23.62:8080']; + // req.get('Origin') 请求头中数据包含http://localhost:8080 + // if (allowOrigins.includes(req.get('Origin'))) { + // res.set('Access-Control-Allow-Origin', req.get('Origin')); + // } + + + // 允许所有的域名 + res.set('Access-Control-Allow-Origin', '*'); + + console.log('接收到请求'); + res.send('hello ajax'); +}); + +``` + +**相关响应头介绍:** + +`Access-Control-Allow-Origin`:允许的域名,多个域名使用逗号隔开,设置为 `*`,表示允许所有的域名。 + +`Access-Control-Allow-Credentials`:该字段可选。它的值是一个布尔值,表示是否允许发送 Cookie。默认情况下,Cookie不包括在跨域请求之中 + +`Access-Control-Expose-Headers`:该字段可选。跨域请求时,XMLHttpRequest 对象的 getResponseHeader()方 法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。 + +```js +Access-Control-Allow-Origin: http://api.bob.com +Access-Control-Allow-Credentials: true +Access-Control-Expose-Headers: content-type,cache-control +``` + +**允许跨域请求携带 Cookie** + +在同源请求时,Ajax 发出的请求会默认携带 cookie 信息,无需进行额外的设置。 + +跨域请求中,默认不允许携带Cookie,如果想在跨域请求中携带 cookie,需要满足以下条件: + +1. XMLHttpRequest 对象的 `withCredentials` 属性必须设置为 `true` ,表示允许发送跨域请求时携带身份凭证(包括 Cookie、Authorization 等)。 +2. 服务器端必须设置 `Access-Control-Allow-Credentials` 头信息为 `true` ,表示允许接受跨域请求时携带身份凭证。 +3. 服务器端必须设置 `Access-Control-Allow-Origin` 头信息为具体的域名,不能设置为通配符 `*` ,表示只允许指定的域名访问资源。 +4. 如果在请求头中添加了其他自定义头信息,例如 `Authorization` ,则需要在服务器端设置 `Access-Control-Allow-Headers` 头信息,否则浏览器也不会发送 Cookie。 +5. 所有设置的 Cookie 需要设置相关属性 Secure 和 SameSite=None,才允许被跨域携带。 + +## JSONP + +### 实现思路 + +```js +实现基础: + 利用 script 标签也可以发送请求,天然支持跨域, script 会把响应到的内容作为 js 代码执行 + +实现步骤:(前端) + 1. 创建 script 标签 + 2. 指定 script 标签的 src 属性值,src 的属性值就是请求地址, 把函数名通过url中的查询字符串传给后端 + 3. 把 script 标签添加到 body 中 + 4. 再把 script 标签从 body 中移除 + 5. 定义获取数据的函数,该函数会被后端响应的内容调用,把数据传进来 + 注意: 在 script 添加到 body 中的瞬间,发起请求,接收响应,调用了函数 + + +实现步骤:(后端) + 1. 从 url 中的查询字符串里取出函数名 + 2. 响应体内容是 js 代码,调用函数的js代码,把数据变为json格式作为函数的参数 + 3. 做出响应 + +``` + +**1) 什么是JSONP ?** + +JSONP(JSON with Padding),是一个非官方的跨域解决方案,纯粹凭借程序员的聪明才智开发出来,只支持 GET 请求方式。 + +在网页有一些标签天生具有跨域能力,比如:img link iframe script,JSONP就是利用 script 标签的跨域能力来发送请求的。 + +```js +原理: +html 中的script标签 浏览器向服务器请求的js代码,会直接执行服务器响应的JS代码。 +后端响应一个 +``` + +**2)JSONP 使用步骤** + +```js +// 1.动态的创建一个script标签 +var script = document.createElement("script"); + +// 2.设置script的 src +script.src = "http://localhost:3000/testAJAX?callback=abc"; + +// 3. 定义函数 +function abc(data) { + alert(data.name); +}; + +// 4.将script添加到 body 中,会发送请求 +document.body.appendChild(script); + +// 5. 将 script 从 body 中删除 +document.body.removeChild(script); +``` + +**3)服务端的处理** + +服务端需要将 js 代码作为响应体: + +```j's +var callback = req.query.callback; +var obj = { + name:"孙悟空", + age:18 +} +res.send(callback+"("+JSON.stringify(obj)+")"); +``` + +### JSONP 缺点 + +``` +只支持 GET 请求 +``` + +### 封装一个 Ajax 函数 + +```js +/* + 选项: + url: 请求地址 + method: 请求方式,默认值 GET + headers: 请求头,默认值 {} + body: 请求体 + dataType: 响应体类型 + success: 成功的回调 + error: 失败的回调 +*/ +function ajax(options) { + // 从 options 取出相关的选项 + const {url, method='GET', headers={}, body, dataType, success=()=>{}, error=()=>{}} = options; + + // 创建 xhr 对象 + const xhr = new XMLHttpRequest(); + + // 如果指定了 dataType + if (dataType) { + xhr.responseType = dataType; + } + + // 监听响应成功的事件 + xhr.onload = () => { + if (xhr.status === 200) { + success(xhr.response); + } else { + error(); + } + } + + // 监听响应失败的事件 + xhr.onerror = error; + + // 请求初始化 + xhr.open(method, url); + + // 设置请求头 + for (let key in headers) { + xhr.setRequestHeader(key, headers[key]); + } + + // 发送 + xhr.send(body); + + +} +``` + + + +# Ajax 记账本 + +## 数据请求API + +```js +获取指定用户的账单: GET /api/account/用户ID +给指定用户添加账单: POST /api/account/用户ID +删除账单: DELETE /api/account/账单ID +``` + +## 流程 + +```js +1. 发起请求获取该用户的账单信息 +2. 添加账单 + ① 点击按钮 弹出表单 + ② 填写表单点击提交按钮,监听了表单提交事件,自己处理,阻止默认提交 + ③ 提交事件触发之后,使用formdata获取表单的内容,formdata作为请求体,发送请求 + ④ 当后端确定添加成功之后,重新请求数据,清空原来的,添加新的 +3. 删除账单 + ① 事件委托给删除按钮监听事件,提前使用自定义属性保存账单ID + ② 点击删除按钮之后,发送请求删除 + ③ 确定后端删除成功之后,删除元素 + +``` + + + diff --git a/docs/front-end/07-ajax/index.md b/docs/front-end/07-ajax/index.md new file mode 100644 index 00000000..80d2b25c --- /dev/null +++ b/docs/front-end/07-ajax/index.md @@ -0,0 +1 @@ +# Ajax使用基础 \ No newline at end of file