React 快速上手 - 09 數(shù)據(jù)請求 fetch
本文重點(diǎn)在 fetch
基礎(chǔ)使用、配置、實(shí)戰(zhàn),如果你很熟練了,可以直接 pass
目標(biāo)
掌握 fetch
使用
基礎(chǔ)使用
詳細(xì)配置
同步請求
跨平臺(tái) cross-fetch
環(huán)境
react 16.3.2
fetch 內(nèi)置
cross-fetch 2.2.0
1 fetch 基礎(chǔ)使用
1.1 數(shù)據(jù)結(jié)構(gòu)
我在 easy-mock
上準(zhǔn)備了模擬數(shù)據(jù)
www./mock/59801f…
[
{
"id" : "610000200102261253" ,
"name" : "薛洋"
},
{
"id" : "350000199603020600" ,
"name" : "許磊"
},
{
"id" : "310000198105081812" ,
"name" : "崔娟"
},
{
"id" : "820000197101010860" ,
"name" : "石霞"
}
]
復(fù)制代碼
一個(gè)列表,兩個(gè)字段 id
name
1.2 讀取
fetch(
''https://www./mock/59801fd8a1d30433d84f198c/example/user/all''
)
.then(res => res.json())
.then(data => {
console .log(data)
this .setState({users : data})
})
.catch(e => console .log(''錯(cuò)誤:'' , e))
復(fù)制代碼
fetch
是瀏覽器內(nèi)置對象,所以我們不用安裝包,直接使用
使用流程
fetch ...
then => res.json()
then => data
注意需要執(zhí)行一次 res.json()
方法才能獲取數(shù)據(jù)
1.3 打印
我們獲取數(shù)據(jù)后,設(shè)置 state
,然后正常數(shù)據(jù) render
就行,完整代碼
import React, {Component} from ''react''
class RequestView extends Component {
constructor (props) {
super (props)
this .state = {users : []}
this .handleClick = this .handleClick.bind(this )
}
handleClick() {
fetch(
''https://www./mock/59801fd8a1d30433d84f198c/example/user/all''
)
.then(res => res.json())
.then(data => {
console .log(data)
this .setState({users : data})
})
.catch(e => console .log(''錯(cuò)誤:'' , e))
}
render() {
return (
<div >
<input type ="button" value ="點(diǎn)擊 http-get 方式獲取數(shù)據(jù)" onClickCapture ={this.handleClick} />
<ul >
{this.state.users &&
this.state.users.map((item, index) => (
<li key ={index.toString()} > {item.name}</li >
))}
</ul >
</div >
)
}
}
復(fù)制代碼
打印
codepen.io/ducafecat/p…
2 fetch 配置
我們來好好的看下這個(gè) fetch()
全局方法
我舉兩個(gè)自定義例子,大家體會(huì)下
2.1 form 提交
2.1.1 定義 Headers
請求頭協(xié)議說明
let initHeaders = new Headers()
initHeaders.append(''Accept'' , ''application/json, text/plain, */*'' )
initHeaders.append(''Cache-Control'' , ''no-cache'' )
initHeaders.append(''Content-Type'' , ''application/x-www-form-urlencoded'' )
復(fù)制代碼
因?yàn)槭潜韱危栽O(shè)置 application/x-www-form-urlencoded
2.1.2 定義 init
配置
let data = {uid : 1011 }
let body = `uid=${data.uid} `
const init = {
method : ''POST'' ,
credentials : ''include'' ,
cache: ''no-cache '' ,
headers: initHeaders,
body
}
復(fù)制代碼
method
指定 POST
方式
credentials: ''include''
表示每次都帶上 cookies
headers
請求頭協(xié)議說明
body
數(shù)據(jù),格式 key=val&key=val&key=val
2.1.3 請求提交
fetch(
''https://www./mock/59801fd8a1d30433d84f198c/example/user/login'' ,
init
)
.then(res => res.json())
.then(data => {
this .setState({user : data})
})
.catch(e => console .log(''錯(cuò)誤:'' , e))
復(fù)制代碼
這里就類似我們第一個(gè)基礎(chǔ)例子了
codepen.io/ducafecat/p…
2.2 raw 提交
2.2.1 定義 Headers
let initHeaders = new Headers()
initHeaders.append(''Accept'' , ''application/json, text/plain, */*'' )
initHeaders.append(''Cache-Control'' , ''no-cache'' )
initHeaders.append(''Content-Type'' , ''application/json;charset=UTF-8'' )
復(fù)制代碼
Content-Type
類型需要定義成 application/json;charset=UTF-8
2.2.2 定義 init
let data = {uid : 1011 }
let body = JSON .stringify(data, null , 2 )
const init = {
method : ''POST'' ,
credentials : ''include'' ,
cache: ''no-cache '' ,
headers: initHeaders,
body
}
復(fù)制代碼
json
數(shù)據(jù)需要格式化 JSON.stringify(data, null, 2)
2.2.3 請求提交
fetch(
''https://www./mock/59801fd8a1d30433d84f198c/example/user/login'' ,
init
)
.then(res => res.json())
.then(data => {
this .setState({user : data})
})
.catch(e => console .log(''錯(cuò)誤:'' , e))
復(fù)制代碼
codepen.io/ducafecat/p…
2.3 完整例子
代碼
import React, {Component} from ''react''
class RequestView extends Component {
constructor (props) {
super (props)
this .state = {user : null }
this .handlePostForm = this .handlePostForm.bind(this )
this .handlePostJSON = this .handlePostJSON.bind(this )
}
handlePostForm() {
let initHeaders = new Headers()
initHeaders.append(''Accept'' , ''application/json, text/plain, */*'' )
initHeaders.append(''Cache-Control'' , ''no-cache'' )
initHeaders.append(''Content-Type'' , ''application/x-www-form-urlencoded'' )
let data = {uid : 1011 }
let body = `uid=${data.uid} `
const init = {
method : ''POST'' ,
credentials : ''include'' ,
cache: ''no-cache '' ,
headers: initHeaders,
body
}
fetch(
''https://www./mock/59801fd8a1d30433d84f198c/example/user/login'' ,
init
)
.then(res => res.json())
.then(data => {
this .setState({user : data})
})
.catch(e => console .log(''錯(cuò)誤:'' , e))
}
handlePostJSON() {
let initHeaders = new Headers()
initHeaders.append(''Accept'' , ''application/json, text/plain, */*'' )
initHeaders.append(''Cache-Control'' , ''no-cache'' )
initHeaders.append(''Content-Type'' , ''application/json;charset=UTF-8'' )
let data = {uid : 1011 }
let body = JSON .stringify(data, null , 2 )
const init = {
method : ''POST'' ,
credentials : ''include'' ,
cache: ''no-cache '' ,
headers: initHeaders,
body
}
fetch(
''https://www./mock/59801fd8a1d30433d84f198c/example/user/login'' ,
init
)
.then(res => res.json())
.then(data => {
this .setState({user : data})
})
.catch(e => console .log(''錯(cuò)誤:'' , e))
}
render() {
return (
<div>
<input
type="button"
value="點(diǎn)擊 http-post form 表單"
onClickCapture={this.handlePostForm}
/>
<br />
<input
type="button"
value="點(diǎn)擊 http-post json raw 格式"
onClickCapture={this.handlePostJSON}
/>
{this.state.user && (
<ul>
<li>ID: {this.state.user.id}</li>
<li>Name: {this.state.user.name}</li>
</ul>
)}
</div>
)
}
}
export default RequestView
復(fù)制代碼
動(dòng)圖效果
3 fetch 同步 async / wait
3.1 同步寫法
async handleClick() {
try {
const res = await fetch(
''https://www./mock/59801fd8a1d30433d84f198c/example/user/all''
)
const users = await res.json()
this .setState({users})
} catch (error) {
console .log(''錯(cuò)誤'' , error)
}
}
復(fù)制代碼
函數(shù)本身要定義成 async
res.json()
這個(gè)方法不要忘記調(diào)用
異常處理要用 try ... catch ...
3.2 完成例子
代碼
import React, {Component} from ''react''
class RequestView extends Component {
constructor (props) {
super (props)
this .state = {users : []}
this .handleClick = this .handleClick.bind(this )
}
async handleClick() {
try {
const res = await fetch(
''https://www./mock/59801fd8a1d30433d84f198c/example/user/all''
)
const users = await res.json()
this .setState({users})
} catch (error) {
console .log(''錯(cuò)誤'' , error)
}
}
render() {
return (
<div >
<input
type ="button"
value ="點(diǎn)擊 async / await 方式獲取數(shù)據(jù)"
onClickCapture ={this.handleClick}
/>
<ul >
{this.state.users &&
this.state.users.map((item, index) => (
<li key ={index.toString()} > {item.name}</li >
))}
</ul >
</div >
)
}
}
export default RequestView
復(fù)制代碼
打印
4 fetch 兼容性
好像 fetch
很強(qiáng)啊,不用安裝包,全局方法直接用,但是有一個(gè)小問題,對瀏覽器的依賴,先看下 caniuse 平臺(tái)的報(bào)告:
IE
全陣亡,低版本 Safari
兼容問題,Firefox
Chrome
Opera
如果特性不開的話也會(huì)出問題,懂的同學(xué)說可以瀏覽器配置和打 polyfill
補(bǔ)丁,但是這樣需要自己做很多工作,如果你的代碼需要跑到 node
端呢(因?yàn)?code>API 業(yè)務(wù)層很有可能復(fù)用性很高)。
如果考慮兼容性,所以我們還是用第三方組件
5 cross-fetch 組件
5.1 介紹
cross-fetch
感覺 Star
不是很多么。。。
接著往下看
5.2 多平臺(tái)支持
README 里說了各種平臺(tái)支持、知名項(xiàng)目也在用
是真的么。。。
接著往下看
5.3 包研究
打開文件 package.json
來看下這兩個(gè)包
github.com/bitinn/node…
指向了 github/fetch
github.com/github/fetc…
好多 Star 看著就放心,大家用吧
5.4 例子
yarn add cross-fetch
復(fù)制代碼
import React, {Component} from ''react''
import fetch from ''cross-fetch''
class RequestView extends Component {
constructor (props) {
super (props)
this .state = {users : []}
this .handleClick = this .handleClick.bind(this )
}
async handleClick() {
try {
const res = await fetch(
''https://www./mock/59801fd8a1d30433d84f198c/example/user/all''
)
const users = await res.json()
this .setState({users})
} catch (error) {
console .log(''錯(cuò)誤'' , error)
}
}
render() {
return (
<div >
<input
type ="button"
value ="點(diǎn)擊 cross-fetch 組件方式 獲取數(shù)據(jù)"
onClickCapture ={this.handleClick}
/>
<ul >
{this.state.users &&
this.state.users.map((item, index) => (
<li key ={index.toString()} > {item.name}</li >
))}
</ul >
</div >
)
}
}
export default RequestView
復(fù)制代碼
代碼
參考