亞成成品網(wǎng)站源碼今天的新聞發(fā)布會(huì)
初始化React腳手架
前期準(zhǔn)備
-
1.腳手架: 用來(lái)幫助程序員快速創(chuàng)建一個(gè)基于xxx庫(kù)的模板項(xiàng)目
- 1.包含了所有需要的配置(語(yǔ)法檢查、jsx編譯、devServer…)
- 2.下載好了所有相關(guān)的依賴
- 3.可以直接運(yùn)行一個(gè)簡(jiǎn)單效果
-
2.react提供了一個(gè)用于創(chuàng)建react項(xiàng)目的腳手架庫(kù): create-react-app
-
3.項(xiàng)目的整體技術(shù)架構(gòu)為: react + webpack + es6 + eslint
-
4.使用腳手架開發(fā)的項(xiàng)目的特點(diǎn): 模塊化, 組件化, 工程化
全局安裝工具
首先要在全局安裝create-react-app
,推薦使用yarn來(lái)安裝,因?yàn)閞eact和yarn都是facebook出的。但是大部分人用的npm,也是完全可以,這里用npm演示
全局安裝react腳手架工具:
npm i -g create-react-app
i代表install
,g代表global全局
,create-react-app代表react腳手架
安裝后查看版本:
D:\WebProject\ReactProject>npm create-react-app -v
6.14.16
我們依靠這個(gè)就可以在想要的目錄下面創(chuàng)建react工程
安裝腳手架
切換到想要?jiǎng)?chuàng)建腳手架的目錄
使用命令:create-react-app 工程名字
名字僅限英文,不要用特殊字符
安裝完畢之后,可以看到React提示的四個(gè)命令:
npm start 啟動(dòng)項(xiàng)目Starts the development server.npm run build 打包Bundles the app into static files for production.npm test 測(cè)試模式啟動(dòng)Starts the test runner.npm run eject 將隱藏的webpack配置文件顯示出來(lái)Removes this tool and copies build dependencies, configuration filesand scripts into the app directory. If you do this, you can’t go back!
我們可以查看配置文件,package.json,所有啟動(dòng)短命令已經(jīng)配置好了
輸入npm start
,啟動(dòng)項(xiàng)目
腳手架結(jié)構(gòu)
這種項(xiàng)目也叫SPA項(xiàng)目:
- S–single
- P–page
- A–app
public ---- **靜態(tài)資源文件夾**favicon.icon ------ 網(wǎng)站頁(yè)簽圖標(biāo)index.html -------- **主頁(yè)面,整個(gè)項(xiàng)目只有這一個(gè)html文件,作為基點(diǎn)**logo192.png ------- logo圖logo512.png ------- logo圖manifest.json ----- 應(yīng)用加殼的配置文件robots.txt -------- 爬蟲協(xié)議文件
src ---- **源碼文件夾**App.css -------- App組件的樣式App.js --------- App組件App.test.js ---- 用于給App做測(cè)試index.css ------ 樣式index.js ------- 入口文件logo.svg ------- logo圖reportWebVitals.js--- 頁(yè)面性能分析文件(需要web-vitals庫(kù)的支持)setupTests.js---- 組件單元測(cè)試的文件(需要jest-dom庫(kù)的支持)
啟動(dòng)項(xiàng)目后默認(rèn)頁(yè)面
詳解index.html
作為整個(gè)項(xiàng)目里唯一一個(gè)html文件,也是整個(gè)app的基點(diǎn),有必要詳細(xì)解讀一下
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><!-- %PUBLIC_URL%代表public文件夾的路徑 --><link rel="icon" href="%PUBLIC_URL%/favicon.ico" /><!-- 開啟理想視口,移動(dòng)端適配 --><meta name="viewport" content="width=device-width, initial-scale=1" /><!-- 配置瀏覽器頁(yè)簽顏色(僅支持安卓原生瀏覽器) --><meta name="theme-color" content="#000000" /><!-- 描述網(wǎng)站信息的,搜索引擎會(huì)讀取這個(gè) --><metaname="description"content="Web site created using create-react-app"/><!-- 蘋果手機(jī)的Safari把網(wǎng)頁(yè)添加到主屏幕后,啟動(dòng)圖標(biāo) --><link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /><!-- 將web套殼成為安卓或ios的安裝包用,(應(yīng)用加殼技術(shù)) --><link rel="manifest" href="%PUBLIC_URL%/manifest.json" /><!-- 網(wǎng)頁(yè)tab的名字 --><title>React App</title></head><body><!-- 如果客戶端瀏覽器不支持JS的運(yùn)行 --><noscript>You need to enable JavaScript to run this app.</noscript><!-- 根標(biāo)簽 --><div id="root"></div></body>
</html>
src目錄解析
App組件相關(guān)
webpack入口相關(guān):index.js
如果是用webpack打包,那么默認(rèn)情況下,index.js就是入口文件
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<React.StrictMode><App /></React.StrictMode>
);**上下這兩種寫法是完全等價(jià)的**ReactDOM.render(<App />,document.getElementById('root'))
<React.StrictMode>
這個(gè)<React.StrictMode>并不是ES5的嚴(yán)格模式,而是React檢查子組件是否有不合理的地方
比如:ref=字符串,或者一些過時(shí)的寫法,來(lái)做一些檢查<React.StrictMode><App /></React.StrictMode>
reportWebVitals()
作為入口的最底下的方法,是用來(lái)記錄網(wǎng)頁(yè)的性能檢測(cè)
至于public里的index.html是如何被src的index.js找到的,這個(gè)我們不需要關(guān)心,是React用webpack配置好的。所以index.html的名字是不可以隨便動(dòng)的,動(dòng)了就找不到了。
我們寫一個(gè)小應(yīng)用,只需要去關(guān)注,index.html 主頁(yè)面
,App.js App組件
,index.js 入口文件
,這三個(gè)就夠了。
注意:工程里import 進(jìn)js和jsx都是不需要寫后綴的
寫一個(gè)小demo
1.我們保持public中的Index.html不變
2.修改src下面的APP.js以及index.js文件
App.js: 【注意:創(chuàng)建好的組件一定要暴露出去】
//創(chuàng)建外殼組件APP
import React from 'react'class App extends React.Component{render(){return (<div>Hello world</div>)}
}export default App
index.js: 【主要的作用其實(shí)就是將App這個(gè)組件渲染到頁(yè)面上】
//引入核心庫(kù)
import React from 'react'
import ReactDOM from 'react-dom'
//引入組件
import App from './App'ReactDOM.render(<App />,document.getElementById("root"))
這樣在重新啟動(dòng)應(yīng)用,就成功了。
我們也不建議這樣直接將內(nèi)容放入App組件中,盡量還是用內(nèi)部組件。
我們?cè)陧斠粋€(gè)Hello組件:
import React,{Componet} from 'react'export default class Hello extends Componet{render() {return (<h1>Hello</h1>)}
}
在App組件中,進(jìn)行使用
class App extends Component{render(){return (<div><Hello /></div>)}
}
這樣的結(jié)果和前面是一樣的。
但是由于普通的Js和組件都是js,所一最好組件使用jsx去展示。
樣式模塊化
前面會(huì)有一個(gè)問題,當(dāng)css和組件越來(lái)越多的時(shí)候,如果css不分層不分級(jí),就會(huì)造成混亂的場(chǎng)景,同時(shí)帶來(lái)樣式?jīng)_突難以管理。
當(dāng)組件逐漸增多起來(lái)的時(shí)候,我們發(fā)現(xiàn),組件的樣式也是越來(lái)越豐富,這樣就很有可能產(chǎn)生兩個(gè)組件中樣式名稱有可能會(huì)沖突,這樣會(huì)根據(jù)引入App這個(gè)組件的先后順序,后面的會(huì)覆蓋前面的。
同名造成的沖突
傳統(tǒng)的引入方式:
修改后的引入方式:
為了避免這樣的樣式?jīng)_突,我們采用下面的形式:
1.將css文件名修改: hello.css — >hello.module.css
css內(nèi)部不用做出修改,也就是以對(duì)象形式進(jìn)行css導(dǎo)入
注意:不要用{}套css對(duì)象,這玩意只是個(gè)標(biāo)記,不是解構(gòu)出來(lái)的!!!
會(huì)如果套了會(huì)導(dǎo)致對(duì)象獲取不到!!!
2.引入并使用的時(shí)候改變方式:
import React from "react";
//引入css,此時(shí)css都以對(duì)象形式存在hello中
import hello from "./hello.module.css"export default class Hello extends React.Component{render(){return(// 以對(duì)象形式獲取css<div className={hello.title}>Hello world</div>)}
}
逆天導(dǎo)入方法
有些項(xiàng)目為了避免大量導(dǎo)入import時(shí)導(dǎo)致后面有一串路徑,就采用這種簡(jiǎn)寫方式,即每個(gè)文件夾下組件名和css名字都是 index的名字,這種情況下,導(dǎo)入的路徑寫到包就可以了,因?yàn)槿绻粚懽詈蟮奈募?#xff0c;默認(rèn)就導(dǎo)入index
就會(huì)從這種具體到文件的導(dǎo)入
import Hello from './component/Hello/hello.jsx'
import Welcome from './component/Welcome/welcome.jsx'
變成這種,導(dǎo)入截止到包名,后綴默認(rèn)用index
import Hello from './component/Hello'
import Welcome from './component/Welcome'
這種導(dǎo)入方法肯定是不推薦的,但是有的公司可能就會(huì)用到這種,所以要提一下
React插件推薦
可以快速幫助你創(chuàng)建模板
比如輸入rcc,自動(dòng)根據(jù)文件名創(chuàng)建類組件
rcc:react class component
輸入rfc,自動(dòng)根據(jù)文件名創(chuàng)建函數(shù)式組件
rfc:react function component
回車就自動(dòng)生成類組件了,函數(shù)式組件也是一樣
等等一些其他的快捷鍵可以自己去查,非常方便
組件化編碼的流程
- 拆分組件: 拆分界面,抽取組件 (頁(yè)面拆組件的過程中如果拆完了不知道叫啥名字,多半是沒拆好)
- 實(shí)現(xiàn)靜態(tài)組件: 使用組件實(shí)現(xiàn)靜態(tài)頁(yè)面效果
- 實(shí)現(xiàn)動(dòng)態(tài)組件
3.1 動(dòng)態(tài)顯示初始化數(shù)據(jù)(數(shù)據(jù)驅(qū)動(dòng)頁(yè)面變化)
3.1.1 數(shù)據(jù)類型
3.1.2 數(shù)據(jù)名稱
3.1.2 保存在哪個(gè)組件?
3.2 交互(從綁定事件監(jiān)聽開始)
腳手架插件
nanoId
相比于uuid更加輕量化,生成一個(gè)唯一id
UUID:生成唯一時(shí)間戳的庫(kù)
npm i uuid
(庫(kù)比較大)
npm i nanoid
(庫(kù)小,很快安裝)/ yarn add nanoid
用法:
import {nanoid} from 'nanoid'
//調(diào)用,直接就可以生成一個(gè)隨機(jī)ID
nanoid()
PropTypes
腳手架本身并不自帶這個(gè),需要自行安裝,完成類型的約束
用npm進(jìn)行安裝,安裝后即可進(jìn)行操作,對(duì)傳入?yún)?shù)進(jìn)行類型約束
npm install prop-types
static propTypes = {addTodo: proptypes.func.isRequired,
};
TodoList組件Demo總結(jié)
拆分組件、實(shí)現(xiàn)靜態(tài)組件,注意:className、style的寫法
動(dòng)態(tài)初始化列表,如何確定將數(shù)據(jù)放在哪個(gè)組件的state中?
- 1)某個(gè)組件使用:放在其自身的state中
- 2)某些組件使用:放在他們共同的父組件state中(官方稱此操作為:狀態(tài)提升)
關(guān)于父子之間通信:
- 1)【父組件】給【子組件】傳遞數(shù)據(jù):通過props傳遞
- 2)【子組件】給【父組件】傳遞數(shù)據(jù):通過props傳遞,要求父提前給子傳遞一個(gè)函數(shù)
注意defaultChecked 和 checked的區(qū)別,類似的還有:defaultValue 和 value
狀態(tài)在哪里,操作狀態(tài)的方法就在哪里
兄弟之間的組件通信,用Pub-Sub訂閱機(jī)制實(shí)現(xiàn),后續(xù)會(huì)有
腳手架集成Axios
Ajax和Axios是啥就不多說(shuō)了
React本身并不帶這些插件,所以需要額外去引入這些插件
前期安裝插件
Axios官網(wǎng)
npm安裝Axios npm install axios
npm查看版本 npm list axios
查看package里的依賴
JSX內(nèi)導(dǎo)入
安裝完成后就可以使用這種方式在JSX內(nèi)導(dǎo)入
import axios from "axios";
方法里面發(fā)起Get請(qǐng)求,其他的用法可以看官網(wǎng):Axios請(qǐng)求官網(wǎng)例子
startAxios = () => {// 這里會(huì)先看自身有沒有這個(gè)路徑下的資源,沒有的話才會(huì)去轉(zhuǎn)發(fā)給代理服務(wù)器axios.get("http://localhost:3000/api/test").then((response) => {console.log("成功了", response.data);},(error) => {console.log("失敗了", error);});};
請(qǐng)求發(fā)起后發(fā)生跨域問題
這個(gè)時(shí)候就需要代理來(lái)解決跨域問題,跨域?yàn)槭裁匆么硎鞘裁凑?qǐng)自行搜索
請(qǐng)求實(shí)際上是已經(jīng)到了server,但是Ajax引擎不許跨域的值返回,所以跨域給攔下來(lái)的本質(zhì)是Ajax引擎把響應(yīng)給攔住了
代理服務(wù)器與server是同一個(gè)域名+端口上的
只完成一個(gè)轉(zhuǎn)發(fā)功能,代理服務(wù)器把請(qǐng)求轉(zhuǎn)到Server上,Server的內(nèi)容還給代理,代理上因?yàn)闆]有Ajax引擎,就把返回來(lái)的數(shù)據(jù)還給Client,由于代理與Client同源,沒有跨域限制,也就解決了跨域問題
代理配置
package.json配置
可以叫做全局代理,因?yàn)樗苯訉⒋砼渲迷诹伺渲梦募?package.json
中
"proxy":"http://localhost:5000"
// "proxy":"請(qǐng)求的地址"
追加的配置文件
這樣配置代理時(shí),首先會(huì)在在原請(qǐng)求地址http://localhost:3000/api/test
上訪問,如果訪問不到資源,就會(huì)轉(zhuǎn)發(fā)到這里配置的地址上去請(qǐng)求,也就是http://localhost:5000/api/test
,如果這時(shí)候還沒有,就404
說(shuō)明:
- 優(yōu)點(diǎn):配置簡(jiǎn)單,前端請(qǐng)求資源時(shí)可以不加任何前綴。
- 缺點(diǎn):不能配置多個(gè)代理。
- 工作方式:上述方式配置代理,當(dāng)請(qǐng)求了3000不存在的資源時(shí),那么該請(qǐng)求會(huì)轉(zhuǎn)發(fā)給5000 (優(yōu)先匹配前端資源)
修改了配置類的操作一定要重啟!!!
setupProxy.js配置
這里不用記,會(huì)查會(huì)配即可,但是要注意 http-proxy-middleware 與腳手架的版本兼容
一定在src目錄下!!!
-
第一步:創(chuàng)建代理配置文件
在src下創(chuàng)建配置文件:src/setupProxy.js
-
編寫setupProxy.js配置具體代理規(guī)則:
const proxy = require('http-proxy-middleware')module.exports = function(app) {app.use(proxy('/api1', { //api1是需要轉(zhuǎn)發(fā)的請(qǐng)求(所有帶有/api1前綴的請(qǐng)求都會(huì)轉(zhuǎn)發(fā)給5000)target: 'http://localhost:5000', //配置轉(zhuǎn)發(fā)目標(biāo)地址(能返回?cái)?shù)據(jù)的服務(wù)器地址)changeOrigin: true, //控制服務(wù)器接收到的請(qǐng)求頭中host字段的值/*changeOrigin設(shè)置為true時(shí),服務(wù)器收到的請(qǐng)求頭中的host為:localhost:5000changeOrigin設(shè)置為false時(shí),服務(wù)器收到的請(qǐng)求頭中的host為:localhost:3000changeOrigin默認(rèn)值為false,但我們一般將changeOrigin值設(shè)為true*/pathRewrite: {'^/api1': ''} //去除請(qǐng)求前綴,保證交給后臺(tái)服務(wù)器的是正常請(qǐng)求地址(必須配置)}),proxy('/api2', { target: 'http://localhost:5001',changeOrigin: true,pathRewrite: {'^/api2': ''}})) }
兩個(gè)關(guān)鍵配置屬性詳解:
changeOrigin:
控制服務(wù)器收到的請(qǐng)求頭中Host的值(本次請(qǐng)求從哪來(lái)的)
true:Origin是走代理的,false:Origin不走代理,是走代理前的host 。
一般都是true,避免后端做奇奇怪怪的check
changeOrigin設(shè)置為true時(shí),服務(wù)器收到的請(qǐng)求頭中的host為:localhost:5000
changeOrigin設(shè)置為false時(shí),服務(wù)器收到的請(qǐng)求頭中的host為:localhost:3000
changeOrigin默認(rèn)值為false,但我們一般將changeOrigin值設(shè)為true
pathRewrite:
重寫請(qǐng)求路徑(必須) { "要被替換的路徑": "替換成啥" },這里的規(guī)則是去掉了 /api1
相當(dāng)于去掉了 /api1 對(duì)于后端來(lái)說(shuō)不會(huì)有api1的前綴,這只是前端區(qū)分請(qǐng)求走哪個(gè)代理的標(biāo)識(shí),真正發(fā)起請(qǐng)求給后端要把這種標(biāo)識(shí)干掉當(dāng)然,這種做法也不絕對(duì),也可以把重寫的路徑換成需要的東西,靈活配置即可
說(shuō)明:
- 優(yōu)點(diǎn):可以配置多個(gè)代理,可以靈活的控制請(qǐng)求是否走代理。
- 缺點(diǎn):配置繁瑣,前端請(qǐng)求資源時(shí)必須加前綴。
setupProxy.js配置過程中遇到的坑
參考文檔
因?yàn)?code>const proxy = require("http-proxy-middleware");這個(gè)中間件的版本不兼容,導(dǎo)致無(wú)法啟動(dòng)項(xiàng)目,具體現(xiàn)象是:啟動(dòng)后臺(tái)無(wú)報(bào)錯(cuò),但是頁(yè)面無(wú)內(nèi)容
要把第一句的中間件獲取換成這個(gè),項(xiàng)目就可以正常啟動(dòng)了
const {createProxyMiddleware: proxy} =require('http-proxy-middleware');
例子
分別根據(jù) /api1
和 /api2
這兩個(gè)前綴,去到不同的server上面
代碼如下
可以看到都是訪問自己的前端端口,如果當(dāng)前資源沒找到,就會(huì)去找上面配置的代理路徑(如果配了多個(gè)url前綴
,就會(huì)根據(jù)url前綴
去不同server)
class App extends React.Component {getData1 = () => {axios.get("http://localhost:3000/api1/search/users2").then((response) => {console.log("成功了", response.data);},(error) => {console.log("失敗了", error);});};getData2 = () => {axios.get("http://localhost:3000/api2/search/users2").then((response) => {console.log("成功了", response.data);},(error) => {console.log("失敗了", error);});};render() {return (<div className="todo-container"><button onClick={this.getData1}>獲取數(shù)據(jù)1</button><button onClick={this.getData2}>獲取數(shù)據(jù)2</button></div>);}
}
export default App;
執(zhí)行結(jié)果:
兩個(gè)node的Server也都正常執(zhí)行了
兄弟組件傳值Pub-Sub
之前可以看到不同的組件之間傳值只能通過state的狀態(tài)提升來(lái)進(jìn)行傳值,但是很明顯這么做在大量數(shù)據(jù)交互的時(shí)候會(huì)變得巨難管理,所以我們要引入Pub-Sub.js來(lái)實(shí)現(xiàn)兄弟組件傳值。
PubSub組件傳值官網(wǎng)
npm安裝命令
npm install pubsub-js
版本查看
npm pubsub-js -v
快速起步
import PubSub from 'pubsub-js' //引入
PubSub.subscribe('用于識(shí)別的key', function(msg, data){ }); //訂閱
PubSub.publish('用于識(shí)別的key', data) //發(fā)布消息
注意:
適用于任意組件之前的消息溝通
誰(shuí)用誰(shuí)接,誰(shuí)傳誰(shuí)發(fā)
特別注意:
一定要先開啟監(jiān)聽,再發(fā)布,要不然發(fā)半天沒人聽發(fā)了也沒有用
發(fā)布消息(publish)
消息發(fā)布,第一個(gè)參數(shù)訂閱key(后續(xù)訂閱會(huì)用到),第二個(gè)參數(shù)是值,下面這兩個(gè)都是完全可以的傳值方式
PubSub.publish('MY TOPIC', 'hello world!');
PubSub.publish('MY TOPIC', { info: "info" });還有一種同步發(fā)布,但是這種性能略強(qiáng),但是不推薦,但有可能出現(xiàn)安全問題,慎重。用上面那兩個(gè)就夠了
PubSub.publishSync('MY TOPIC', 'hello world!');
比如這種,就可以傳入對(duì)象進(jìn)去,發(fā)布給obj-key
的這個(gè)消息訂閱方
注意這里傳入對(duì)象不要用展開符
訂閱消息(subscribe)
// msg是必須接受的,如果實(shí)在不想接受可以傳個(gè)占位符
// var mySubscriber = function (_, data)
var mySubscriber = function (msg, data) {console.log(msg, data);
};// 生成一個(gè)token是為了后續(xù)停止訂閱用的,有專門api來(lái)關(guān)閉訂閱
var token = PubSub.subscribe('MY TOPIC', mySubscriber);// 關(guān)閉訂閱(可以用在組件卸載這種)
PubSub.unsubscribe(token);
也可以用箭頭函數(shù),這兩種寫法是完全等價(jià)的
var mySubscriber = function (msg, data) {console.log(msg, data);
};// 生成一個(gè)token是為了后續(xù)停止訂閱用的,有專門api來(lái)關(guān)閉訂閱
var token = PubSub.subscribe('MY TOPIC', (msg, data)=>{// 打印出來(lái)的msg就是訂閱keyconsole.log(msg, data);
});
在實(shí)際代碼中加入,發(fā)現(xiàn)token作用域出現(xiàn)問題了,所以要改一下
用this修改一下,再用箭頭函數(shù)優(yōu)化一下
代碼示例
三個(gè)組件集成在一個(gè)文件里,實(shí)現(xiàn)測(cè)試
import React from "react";
import PubSub from "pubsub-js";
import "./App.css";// 一定要先開啟監(jiān)聽,再發(fā)布,要不然發(fā)半天沒人聽發(fā)了也沒有用
class PublishInfo extends React.Component {publishInfo = () => {var obj = { info: "info" };PubSub.publish("publish-key", obj);};render() {return (<div><button onClick={this.publishInfo}>publishInfo(后開啟發(fā)布)</button></div>);}
}// 一定要先開啟監(jiān)聽,再發(fā)布,要不然發(fā)半天沒人聽發(fā)了也沒有用
class SubscriptInfo extends React.Component {subScriptInfo = () => {this.token = PubSub.subscribe("publish-key", (msg, data) => {// 這里只接受一個(gè)data也是可以的console.log(msg, data);});};unsubscribeBeforeUnmount = () => {// 模擬組件卸載前函數(shù),暫停監(jiān)聽。當(dāng)然放在生命周期里面也可以console.log("tokenID:", this.token, PubSub.unsubscribe(this.token));};render() {return (<div><button onClick={this.subScriptInfo}>subScriptInfo(先開啟監(jiān)聽)</button><button onClick={this.unsubscribeBeforeUnmount}>模擬卸載組件(最后)</button></div>);}
}
// 創(chuàng)建并暴露App組件
class App extends React.Component {render() {return (<div><SubscriptInfo /><PublishInfo /></div>);}
}
export default App;
極端場(chǎng)景
這種,從F組件給C組件傳值,只要key是一樣得,就可以通信到,所以跨組件傳值非常方便
Fetch發(fā)送請(qǐng)求(擴(kuò)展)
首先 fetch 也是一種發(fā)送請(qǐng)求的方式,它是在 xhr 之外的一種,我們平常用的 Jquery 和 axios 都是封裝了 xhr 的第三方庫(kù),而 fetch 是js官方自帶的庫(kù)(也是XMLHttpRequest的升級(jí)版),同時(shí)它也采用的是 Promise 的方式,大大簡(jiǎn)化了寫法
由于是js內(nèi)置,所以甚至可以在控制臺(tái)運(yùn)行
在代碼里如何使用呢?
fetch("https://api.github.com/users/ruanyf").then((response) => response.json()).then((json) => console.log(json)).catch((err) => console.log("Request Failed", err));
搞個(gè)按鈕觸發(fā)一下fetch就可以用了
它的使用方法和 axios 非常的類似,都是返回 Promise 對(duì)象,但是不同的是, fetch 關(guān)注分離,它在第一次請(qǐng)求時(shí),不會(huì)直接返回?cái)?shù)據(jù),會(huì)先返回聯(lián)系服務(wù)器的狀態(tài),在第二步中才能夠獲取到數(shù)據(jù)
我們需要在第一次 then
中返回 response.json()
因?yàn)檫@個(gè)是包含數(shù)據(jù)的 promise 對(duì)象,response.json()
是一個(gè)異步操作,取出所有內(nèi)容,并將其轉(zhuǎn)為 JSON 對(duì)象。再調(diào)用一次 then
方法即可獲取到對(duì)象,
但是這么多次的調(diào)用 then
并不是我們所期望的,相信看過之前生成器的文章的伙伴,已經(jīng)有了想法。
我們可以利用 async
和 await
配合使用,來(lái)簡(jiǎn)化代碼
可以將 await
理解成一個(gè)自動(dòng)執(zhí)行的 then
方法,這樣清晰多了
async function getJSON() {let url = 'https://xxx';try {let response = await fetch(url);return await reasponse.json();} catch (error) {console.log('Request Failed', error);}
}
最后關(guān)于錯(cuò)誤對(duì)象的獲取可以采用 try...catch
來(lái)實(shí)現(xiàn)
關(guān)于 fetch 的更多內(nèi)容
強(qiáng)烈推薦阮一峰老師的博文:fetch