「寫在前面」
本文為黑馬程序員 AJAX 教程的學習筆記。本著自己學習、分享他人的態度,分享學習筆記,希望能對大家有所幫助。推薦先按順序閱讀往期內容:
1. AJAX 學習筆記(Day1)
目錄
-
3 AJAX 原理 -
3.1 XMLHttpRequest -
3.2 Promise -
3.3 封裝簡易版 axios -
3.4 案例 - 天氣預報
-
3 AJAX 原理
3.1 XMLHttpRequest
P33:https://www.bilibili.com/video/BV1MN411y7pw?p=33
什么是 XMLHttpRequest:

關系:axios 內部采用 XMLHttpRequest 與服務器交互

使用 XMLHttpRequest 步驟:
-
創建 XMLHttpRequest 對象 -
配置請求方法和請求 url 地址 -
監聽 loadend 事件,接收響應結果 -
發起請求

XMLHttpRequest - 查詢參數
P34:https://www.bilibili.com/video/BV1MN411y7pw?p=34
定義:瀏覽器提供給服務器的額外信息,讓服務器返回瀏覽器想要的數據
語法:http://xxxx.com/xxx/xxx?參數名1=值1&參數名2=值2
案例:使用XHR攜帶查詢參數,展示某個省下屬的城市列表
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://hmajax.itheima.net/api/city?pname=遼寧省')
xhr.addEventListener('loadend', () => {
console.log(xhr.response)
const data = JSON.parse(xhr.response)
console.log(data)
document.querySelector('.city-p').innerHTML = data.list.join('<br>')
})
xhr.send()
案例:地區查詢
P35:https://www.bilibili.com/video/BV1MN411y7pw?p=35

XMLHttpRequest - 數據提交
P36:https://www.bilibili.com/video/BV1MN411y7pw?p=36
步驟和語法:
-
沒有 axios 了,我們需要自己設置請求頭 Content-Type:application/json,來告訴服務器端,我們發過去的內容類型是 JSON 字符串,讓他轉成對應數據結構取值使用 -
沒有 axios 了,我們前端要傳遞的請求體數據,也沒人幫我把 JS 對象轉成 JSON 字符串了,需要我們自己轉換 -
原生 XHR 需要在 send 方法調用時,傳入請求體攜帶
const xhr = new XMLHttpRequest()
xhr.open('請求方法', '請求url網址')
xhr.addEventListener('loadend', () => {
console.log(xhr.response)
})
// 1. 告訴服務器,我傳遞的內容類型,是 JSON 字符串
xhr.setRequestHeader('Content-Type', 'application/json')
// 2. 準備數據并轉成 JSON 字符串
const user = { username: 'itheima007', password: '7654321' }
const userStr = JSON.stringify(user)
// 3. 發送請求體數據
xhr.send(userStr)
3.2 Promise
P37:https://www.bilibili.com/video/BV1MN411y7pw?p=37
什么是 Promise ?
Promise 對象用于表示一個異步操作的最終完成(或失敗)及其結構值
Promise 的好處?
-
邏輯更清晰(成功或失敗會關聯后續的處理函數) -
了解 axios 函數內部運作的機制 -
能解決回調函數地獄問題

語法:
// 1. 創建 Promise 對象
const p = new Promise((resolve, reject) => {
// 2. 執行異步任務-并傳遞結果
// 成功調用: resolve(值) 觸發 then() 執行
// 失敗調用: reject(值) 觸發 catch() 執行
})
// 3. 接收結果
p.then(result => {
// 成功
}).catch(error => {
// 失敗
})
Promise - 三種狀態
P38:https://www.bilibili.com/video/BV1MN411y7pw?p=38
一個Promise對象,必然處于以下幾種狀態之一:
-
待定(pending):初始狀態,既沒有被兌現,也沒有被拒絕 -
已兌現(fulfilled):操作成功完成 -
已拒絕(rejected):操作失敗
注意:Promise對象一旦被兌現/拒絕就是已敲定了,狀態無法再被改變

案例:使用Promise + XHR 獲取省份列表
P39:https://www.bilibili.com/video/BV1MN411y7pw?p=39

3.3 封裝簡易版 axios
封裝_簡易axios_獲取省份列表
P40:https://www.bilibili.com/video/BV1MN411y7pw?p=40
需求:基于 Promise + XHR 封裝 myAxios 函數,獲取省份列表展示
/**
* 目標:封裝_簡易axios函數_獲取省份列表
* 1. 定義myAxios函數,接收配置對象,返回Promise對象
* 2. 發起XHR請求,默認請求方法為GET
* 3. 調用成功/失敗的處理程序
* 4. 使用myAxios函數,獲取省份列表展示
*/
// 1. 定義myAxios函數,接收配置對象,返回Promise對象
function myAxios(config) {
return new Promise((resolve, reject) => {
// 2. 發起XHR請求,默認請求方法為GET
const xhr = new XMLHttpRequest()
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
// 3. 調用成功/失敗的處理程序
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
xhr.send()
})
}
// 4. 使用myAxios函數,獲取省份列表展示
myAxios({
url: 'http://hmajax.itheima.net/api/province'
}).then(result => {
console.log(result)
document.querySelector('.my-p').innerHTML = result.list.join('<br>')
}).catch(error => {
console.log(error)
document.querySelector('.my-p').innerHTML = error.message
})
封裝_簡易axios_獲取地區列表
P41:https://www.bilibili.com/video/BV1MN411y7pw?p=41
需求:修改 myAxios 函數支持傳遞查詢參數,獲取"遼寧省","大連市"對應地區列表展示
function myAxios(config) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
// 1. 判斷有params選項,攜帶查詢參數
if (config.params) {
// 2. 使用URLSearchParams轉換,并攜帶到url上
const paramsObj = new URLSearchParams(config.params)
const queryString = paramsObj.toString()
// 把查詢參數字符串,拼接在url?后面
config.url += `?${queryString}`
}
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
xhr.send()
})
}
// 3. 使用myAxios函數,獲取地區列表
myAxios({
url: 'http://hmajax.itheima.net/api/area',
params: {
pname: '遼寧省',
cname: '大連市'
}
}).then(result => {
console.log(result)
document.querySelector('.my-p').innerHTML = result.list.join('<br>')
})
封裝_簡易axios_注冊用戶
P42:https://www.bilibili.com/video/BV1MN411y7pw?p=42
需求:修改 myAxios 函數支持傳遞請求體數據,完成注冊用戶功能
function myAxios(config) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
if (config.params) {
const paramsObj = new URLSearchParams(config.params)
const queryString = paramsObj.toString()
config.url += `?${queryString}`
}
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
// 1. 判斷有data選項,攜帶請求體
if (config.data) {
// 2. 轉換數據類型,在send中發送
const jsonStr = JSON.stringify(config.data)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(jsonStr)
} else {
// 如果沒有請求體數據,正常的發起請求
xhr.send()
}
})
}
document.querySelector('.reg-btn').addEventListener('click', () => {
// 3. 使用myAxios函數,完成注冊用戶
myAxios({
url: 'http://hmajax.itheima.net/api/register',
method: 'POST',
data: {
username: 'itheima999',
password: '666666'
}
}).then(result => {
console.log(result)
}).catch(error => {
console.dir(error)
})
})
3.4 案例 - 天氣預報

P43:https://www.bilibili.com/video/BV1MN411y7pw?p=43
P44:https://www.bilibili.com/video/BV1MN411y7pw?p=44
P45:https://www.bilibili.com/video/BV1MN411y7pw?p=45
P46:https://www.bilibili.com/video/BV1MN411y7pw?p=46

本文由 mdnice 多平臺發布