react自看
文章目錄
- 1 為什么要使用React
- 2 React的定義
- 3 React的三大特性
- 4 React入門
- 4.1 hello_react
- 4.2 虛擬DOM的創(chuàng)建
- 4.3 JSX
- 4.4 模塊與組件,模塊化與組件化的理解
- 5 React面向組件編程
- 5.1 基本理解和使用
- 5.2 組件實(shí)例的三大核心屬性
- 5.2.1 state
- 5.2.2 props
- 5.2.3 ref
- 5.3 React中的事件處理
- 5.4 React中收集表單數(shù)據(jù)
- 5.4.1 非受控組件與非受控組件
- 5.5 組件的 生命周期
- 5.5.1 效果
- 5.5.2. 掛載與卸載
- 5.5.3 理解
- 5.5.4 生命周期流程圖(舊)
- 5.5.5 生命周期流程圖(新)
- 5.5.6 重要勾子和即將廢棄的勾子
- 5.6 虛擬DOM與DOM Diffing算法
- 6 React應(yīng)用(基于React腳手架)
- 6.1 使用create-react-app創(chuàng)建react應(yīng)用
- 6.1.1 react腳手架
- 6.1.2 創(chuàng)建項(xiàng)目并啟動(dòng)
- 6.1.3 react腳手架項(xiàng)目結(jié)構(gòu)
- 6.1.4 功能界面的組件化編碼流程(通用)
- 6.2 react ajax
- 6.2.1 理解
- 6.2.2 axios
- 6.2.3 react腳手架配置代理總結(jié)
- 6.2.4 消息訂閱-發(fā)布機(jī)制
- 6.2.5 擴(kuò)展:Fetch(關(guān)注分離思想)
- 7 React路由
- 7.1 相關(guān)理解
- 7.1.1 SPA 的理解
- 7.1.2 路由的理解
- 7.1 .3 react-router-dom的理解
- 7.2 react-router-dom相關(guān)API
- 7.2.1 內(nèi)置組件
- 7.2.2. 其它
- 8 代碼
- 9 參考
1 為什么要使用React
- 原生的JavaScript操作DOM繁瑣,效率低(DOM-API操作UI)
- 使用JavaScript,包括jQuery直接操作DOM,瀏覽器會進(jìn)行大量的重繪和重排(雖然jQuery簡化了操作DOM的步驟,但依然效率低下)
- 原生的JavaScript沒有組件化編碼方案,代碼復(fù)用率低
2 React的定義
React的定義:用于構(gòu)建用戶界面的JavaScript庫。
關(guān)鍵字:
換句話來說,React所做的有三步
也就是說React也可以定義為一個(gè)將數(shù)據(jù)渲染為HTML視圖的開源JavaScript庫。
3 React的三大特性
命令式編程 VS 聲明式編程:
簡單來說,命令式編程就是通過代碼來告訴計(jì)算機(jī)去做什么。
而聲明式編程是通過代碼來告訴計(jì)算機(jī)你想要做什么,讓計(jì)算機(jī)想出如何去做。
舉個(gè)生活中的例子就是:
命令式編程:我想喝一個(gè)冰可樂,然后我就會對身邊的XXX說:“XXX,你去廚房,打開冰箱,拿出一瓶冰可樂,打開之后送過來給我。”
聲明式編程:我想喝一個(gè)冰可樂,然后我就會對身邊的XXX說:“XXX,我想喝冰可樂。”而具體他是怎么拿到的冰可樂,怎么送過來的,是下樓買的還是在冰箱里拿的,我并不關(guān)心,我只關(guān)心我喝冰可樂的需求是否得到了滿足。
用代碼來舉個(gè)例子:
如果我要在界面上展示一個(gè)按鈕,并且點(diǎn)擊按鈕后會改變該按鈕的class。
用DOM編程寫的代碼就是命令式編程:首先你要指揮瀏覽器,第一步先要找到id為container的節(jié)點(diǎn),然后創(chuàng)建一個(gè)button element,接著給這個(gè)button添加一個(gè)class name,然后添加一個(gè)點(diǎn)擊事件,最后將button添加到container節(jié)點(diǎn)里。這整個(gè)過程每一步操作都是命令式的,一步一步告訴瀏覽器要做什么。
btn.className = "btn red " ;
btn.textContent = “Demo” ;
btn.onclick = function ( ) {
if ( this.classList.contains ( “red” ) ) {
this.classList.remove( “red” );
this.classList.add ( “blue” );
}else {
this.classList.remove( “blue” );
this.classList.add ( “red” );
}
};
container.appendChild( btn);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
而要實(shí)現(xiàn)相同功能,采用聲明式編程的React就簡單得多了。
首先我們定義一個(gè)Button組件,在render函數(shù)里通過返回一個(gè)類似HTML的數(shù)據(jù)結(jié)構(gòu),告訴React我要渲染一個(gè)Button,它是id為container的子節(jié)點(diǎn)。Button上的ClassName是動(dòng)態(tài)變化的,當(dāng)點(diǎn)擊按鈕時(shí)class要改變,這樣就可以了。至于render什么時(shí)候被執(zhí)行,是如何渲染到頁面上的,點(diǎn)擊按鈕之后classname是如何更新的,這些都不需要你關(guān)心,你只需要告訴React你希望當(dāng)前的UI應(yīng)該是一個(gè)什么樣的狀態(tài)就可以了。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
組件化的出現(xiàn)大幅度地提升了代碼地復(fù)用率,同時(shí)也改變了前端開發(fā)人員的一個(gè)編程思維
React的靈活性是由于它自身的定位決定的。React是一個(gè)用于構(gòu)建用戶界面的JS庫,對于React來說,這里的用戶界面是一個(gè)抽象的虛擬的用戶界面,其實(shí)就是一個(gè)描述頁面狀態(tài)的數(shù)據(jù)結(jié)構(gòu)。web頁面,移動(dòng)客戶端頁面,VR界面都是用戶界面,只要配合相應(yīng)的渲染器就能在不同的平臺中展示正確的UI界面。
通俗來說,我們可以把React的執(zhí)行結(jié)果想象成一個(gè)視頻文件數(shù)據(jù),在不同的播放器設(shè)備,我們通過轉(zhuǎn)換器將視頻編譯成不同的格式來讓他們在不同的播放器上正常地播放。所以在寫web端React時(shí)我們要額外引入React DOM來做渲染。
此外,React使用虛擬DOM+優(yōu)秀的Diffing算法,盡量減少與真實(shí)DOM的交互,最小化頁面重繪
4 React入門
4.1 hello_react
4.2 虛擬DOM的創(chuàng)建
創(chuàng)建虛擬DOM的兩種方式
- 純JS方式(一般不用,過于繁瑣)
- JSX方式(簡單方便,最終由babel翻譯成js的形式,與用js寫的結(jié)果一樣)
虛擬DOM和真實(shí)DOM
-
React提供一些API來創(chuàng)建一種“特別”的一般js對象
const VDOM = React.createElement('xx',{id:'xx'},'xx')///依次為標(biāo)簽名,標(biāo)簽屬性和標(biāo)簽內(nèi)容- 1
上面創(chuàng)建的就是一個(gè)簡單的虛擬DOM對象
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-nCawKD9t-1624953908993)(https://i.loli.net/2021/04/25/qwd6egtIJMapLmA.png)]
-
我們編碼時(shí)基本只需要操作react的虛擬DOM相關(guān)數(shù)據(jù),react就會轉(zhuǎn)換為真實(shí)的DOM
關(guān)于虛擬DOM總結(jié):
4.3 JSX
鏈接:JSX基本語法規(guī)則
全稱: JavaScript XML
react定義的一種類似于XML的JS擴(kuò)展語法: JS + XML,本質(zhì)上還是JavaScript
是**React.createElement(component, props, …children)**方法的語法糖
作用:用來簡化創(chuàng)建虛擬DOM
- 寫法:var ele =
Hello JSX!
- 它不是字符串(不要加引號),也不是HTML/XML標(biāo)簽
- 它最終產(chǎn)生的就是一個(gè)js對象
標(biāo)簽名任意:HTML標(biāo)簽或其他標(biāo)簽
標(biāo)簽屬性隨意:HTML標(biāo)簽屬性或其它
基本語法規(guī)則
-
標(biāo)簽首字母
? (1)若小寫字母開頭,則將該標(biāo)簽轉(zhuǎn)為HTML中同名元素,若HTML中無該標(biāo)簽對應(yīng)的同名元素,則報(bào)錯(cuò)。
? (2)若大寫字母開頭,則react就去渲染對用的組件,若組件沒有定義,則報(bào)錯(cuò)
-
標(biāo)簽中的js表達(dá)式必須用{ }包含
一定要區(qū)分:【JS語句(代碼)】與【js表達(dá)式】
-
表達(dá)式:一個(gè)表達(dá)式會產(chǎn)生一個(gè)值,可以放在任何一個(gè)需要值的地方
下面這些都是表達(dá)式:
- a
- a+b
- demo(1) //函數(shù)調(diào)用表達(dá)式
- arr.map()
- function test() { }
-
語句(代碼):不產(chǎn)生值
? 下面這些都是語句(代碼):
- if(){}
- for(){}
- switch(){case:xxx}
-
注釋需要寫在花括號{}中
-
樣式的類名指定不要寫class,要寫className
-
內(nèi)聯(lián)樣式要用style={undefined{key:value}}的形式寫第一個(gè){}表示里面是一個(gè)js表達(dá)式,第二個(gè){}表示里面是一個(gè)鍵值對,里面要寫小駝峰的形式, 比如font-size要寫成fontSize
<span style={undefined{color:’#e0e0e0’, fontSize:18} }> myData
-
虛擬DOM只能有一個(gè)根標(biāo)簽,有多個(gè)標(biāo)簽時(shí),可用一個(gè)div包起來
-
標(biāo)簽必須閉合
- 瀏覽器不能直接解析JSX代碼, 需要babel轉(zhuǎn)譯為純JS的代碼才能運(yùn)行
- 只要用了JSX,都要加上type=“text/babel”, 聲明需要babel來處理
4.4 模塊與組件,模塊化與組件化的理解
- 理解:向外提供特定功能的js程序,一般就是一個(gè)js文件
- 為什么要拆成模塊:因?yàn)殡S著業(yè)務(wù)邏輯增加,代碼越來越多且復(fù)雜
- 作用:服用js,簡化js的編寫,提高js運(yùn)行效率
- 理解:用來實(shí)現(xiàn)局部功能的代碼和資源的集合(html/css/js/image等等)
- 為什么一個(gè)界面的功能很復(fù)雜,不可能寫成一整塊,要分成一塊塊寫,然后拼起來
- 作用:復(fù)用編碼,簡化項(xiàng)目編碼,提高運(yùn)行效率
當(dāng)一個(gè)應(yīng)用的js都是以模塊來編寫,這個(gè)應(yīng)用就是一個(gè)模塊化的應(yīng)用
當(dāng)應(yīng)用是以多組件的方式實(shí)現(xiàn),這個(gè)應(yīng)用就是一個(gè)組件化的應(yīng)用
5 React面向組件編程
5.1 基本理解和使用
組件的類型
? 注意:
? (1)組件名必須首字母大寫
? (2)虛擬DOM元素只能有一個(gè)根元素
? (3)虛擬DOM元素必須有結(jié)束標(biāo)簽
簡單組件:無狀態(tài)的組件
復(fù)雜組件:有狀態(tài)(state)的組件
狀態(tài):舉例子說
- 人是有狀態(tài)的,比如今天的精神如何,人的狀態(tài)會影響人的行為
- 組件也是有狀態(tài)的,組件的狀態(tài)驅(qū)動(dòng)頁面,數(shù)據(jù)放在狀態(tài)里
5.2 組件實(shí)例的三大核心屬性
5.2.1 state
- state是組件對象最重要的屬性, 值是==對象(==可以包含多個(gè)key-value的組合),用{}包裹
- 組件被稱為"狀態(tài)機(jī)", 通過更新組件的state來更新對應(yīng)的頁面顯示(重新渲染組件)
- 組件中render方法中的this為組件實(shí)例對象
- 組件自定義的方法中this為undefined(作為事件的回調(diào)使用),如何解決?
- a) 強(qiáng)制綁定this: 通過函數(shù)對象的bind()
- b) 箭頭函數(shù)【要寫成賦值語句+箭頭函數(shù)的形式,類里面不支持function(){ }這種形式】
- 狀態(tài)數(shù)據(jù),不能直接修改或更新,要用setState
5.2.2 props
- 每個(gè)組件對象都會有props(properties的簡寫)屬性
- 組件標(biāo)簽的所有屬性都保存在props中
- 通過標(biāo)簽屬性從組件外向組件內(nèi)傳遞變化的數(shù)據(jù)
- 注意: 組件內(nèi)部不要修改props數(shù)據(jù)
-
內(nèi)部讀取某個(gè)屬性值: this.props.name
-
對props中的屬性值進(jìn)行類型限制和必要性限制
-
第一種方式(React v15.5 開始已棄用):
Person.propTypes = {name: React.PropTypes.string.isRequired,age: React.PropTypes.number }- 1
- 2
- 3
- 4
-
第二種方式(新):使用prop-types庫進(jìn)限制(需要引入prop-types庫)
Person.propTypes = {name: PropTypes.string.isRequired,age: PropTypes.number. }- 1
- 2
- 3
- 4
-
擴(kuò)展屬性:將對象的所有屬性通過props傳遞:<Person {…person}/>
-
默認(rèn)屬性值:
- 1
- 2
- 3
- 4
-
組件類的構(gòu)造函數(shù)
constructor(props){super(props)console.log(props)//打印所有屬性 }- 1
- 2
- 3
- 4
5.2.3 ref
理解:組件內(nèi)的標(biāo)簽可以定義ref屬性來標(biāo)識自己
編碼
-
字符串形式的ref:(已經(jīng)不被react推薦使用)官方說明
<input ref = 'input1'/>- 1
-
回調(diào)形式的ref
<input ref={(c)=>{this.input1 = c}}- 1
-
createRef創(chuàng)建ref容器
- 1
- 2
5.3 React中的事件處理
通過onXxx屬性指定處理函數(shù)(注意大小寫,與原生的js區(qū)分開)
? a) React使用的是自定義(合成)事件, 而不是使用的原生DOM事件 ——目的是為了更好的兼容性
? b) React中的事件是通過事件委托方式處理的(委托給組件最外層的元素) ——目的是為了高效
通過event.target得到發(fā)生事件的DOM元素對象 ——為了避免過度使用ref
不要過度使用ref,當(dāng)發(fā)生事件的DOM正好是要操作的DOM元素時(shí)可以用event.target的形式
5.4 React中收集表單數(shù)據(jù)
5.4.1 非受控組件與非受控組件
非受控組件:現(xiàn)用現(xiàn)取(ref)
受控組件:隨著輸入維護(hù)狀態(tài)為受控組件(onChange , setState)
5.5 組件的 生命周期
5.5.1 效果
需求:定義組件實(shí)現(xiàn)以下功能:
5.5.2. 掛載與卸載
掛載:mount。當(dāng) 組件第一次被渲染到 DOM 中的時(shí)候,就為其設(shè)置一個(gè)計(jì)時(shí)器。這在 React 中被稱為“掛載(mount)”。
卸載:unmount。同時(shí),當(dāng) DOM 中 組件被刪除的時(shí)候,應(yīng)該清除計(jì)時(shí)器。這在 React 中被稱為“卸載(unmount)”
5.5.3 理解
5.5.4 生命周期流程圖(舊)
生命周期的三個(gè)階段(舊)
初始化階段: 由ReactDOM.render()觸發(fā)—初次渲染
? 1). constructor()
? 2). componentWillMount()
? 3). render()
? 4). componentDidMount() = = = =>常用,一般在這個(gè)鉤子中做一些初始化的事,例如開啟定時(shí)器、 發(fā)送網(wǎng)絡(luò)請求、訂閱消息、開啟監(jiān)聽, 發(fā)送ajax請求等
更新階段: 由組件內(nèi)部this.setSate()或父組件重新render觸發(fā)
? 1). shouldComponentUpdate()
? 2). componentWillUpdate()
? 3). render() = = = =>必須要使用
? 4). componentDidUpdate()
卸載組件: 由ReactDOM.unmountComponentAtNode()觸發(fā)
? 1). componentWillUnmount() = = = =>常用,一般在這個(gè)鉤子做一些收尾的工作,例如,關(guān)閉定時(shí) 器、取消訂閱消息
5.5.5 生命周期流程圖(新)
生命周期的三個(gè)階段(新)
**1. ** 初始化階段: 由ReactDOM.render()觸發(fā)—初次渲染
? constructor()
getDerivedStateFromProps(新增,很少用,上官網(wǎng)了解即可)
? (此方法適用于罕見的用例,即 state 的值在任何時(shí)候都取決于 props)
? render()
? componentDidMount()
更新階段: 由組件內(nèi)部this.setSate()或父組件重新render觸發(fā)
? getDerivedStateFromProps
? shouldComponentUpdate()
render()- 1
**getSnapshotBeforeUpdate ** 在更新之前獲取快照,有點(diǎn)實(shí)用意義
componentDidUpdate()- 1
**3. ** 卸載組件: 由ReactDOM.unmountComponentAtNode()觸發(fā)
? componentWillUnmount()
5.5.6 重要勾子和即將廢棄的勾子
- render:必須要使用,初始化渲染或更新渲染調(diào)用
- componentDidMount:一般在這個(gè)鉤子中做一些初始化的事,例如開啟定時(shí)器、 發(fā)送網(wǎng)絡(luò)請求、訂閱消息,開啟監(jiān)聽, 發(fā)送ajax請求等
- componentWillUnmount:做一些收尾工作, 如: 清理定時(shí)器,取消訂閱等
- componentWillMount
- componentWillReceiveProps
- componentWillUpdate
16版本能正常使用,17版本使用會出現(xiàn)警告,下一個(gè)大版本需要加上UNSAFE_前綴才能使用,以后可能會被徹底廢棄,不建議使用。
5.6 虛擬DOM與DOM Diffing算法
經(jīng)典面試題:
1). react/vue中的key有什么作用?(key的內(nèi)部原理是什么?)
2). 為什么遍歷列表時(shí),key最好不要用index?
虛擬DOM中key的作用:
1). 簡單地說: key是虛擬DOM對象的標(biāo)識, 在更新顯示時(shí)key起著極其重要的作用。
2). 詳細(xì)地·說: 當(dāng)狀態(tài)中的數(shù)據(jù)發(fā)生變化時(shí),react會根據(jù)【新數(shù)據(jù)】生成【新的虛擬DOM】, 隨后React進(jìn)行【新虛擬DOM】與【舊虛擬DOM】的diff比較,比較規(guī)則如下:
? a. 舊虛擬DOM中找到了與新虛擬DOM相同的key:
? (1).若虛擬DOM中內(nèi)容沒變, 直接使用之前的真實(shí)DOM
? (2).若虛擬DOM中內(nèi)容變了, 則生成新的真實(shí)DOM,隨后替換掉頁面中之前的真實(shí)DOM
? b. 舊虛擬DOM中未找到與新虛擬DOM相同的key
? 根據(jù)數(shù)據(jù)創(chuàng)建新的真實(shí)DOM,隨后渲染到到頁面
? 1) 若對數(shù)據(jù)進(jìn)行:逆序添加、逆序刪除等破壞順序操作:
? 會產(chǎn)生沒有必要的真實(shí)DOM更新 ==> 界面效果沒問題, 但效率低。
? 2.)如果結(jié)構(gòu)中還包含輸入類的DOM:
? 會產(chǎn)生錯(cuò)誤DOM更新 ==> 界面有問題。
? 3) ==注意!==如果不存在對數(shù)據(jù)的逆序添加、逆序刪除等破壞順序操作, 僅用于渲染列表用于展 示,使用index作為key是沒有問題的。
?
? 3. 開發(fā)中如何選擇key?:
? 1) 最好使用每條數(shù)據(jù)的唯一標(biāo)識作為key, 比如id、手機(jī)號、身份證號、學(xué)號等唯一值。
? 2) 如果確定只是簡單的展示數(shù)據(jù),用index也是可以的。
6 React應(yīng)用(基于React腳手架)
6.1 使用create-react-app創(chuàng)建react應(yīng)用
6.1.1 react腳手架
xxx腳手架: 用來幫助程序員快速創(chuàng)建一個(gè)基于xxx庫的模板項(xiàng)目
1)包含了所有需要的配置(語法檢查、jsx編譯、devServer…)
2) 下載好了所有相關(guān)的依賴、
3)可以直接運(yùn)行一個(gè)簡單效果
react提供了一個(gè)用于創(chuàng)建react項(xiàng)目的腳手架庫: create-react-app
項(xiàng)目的整體技術(shù)架構(gòu)為: react + webpack + es6 + eslint
使用腳手架開發(fā)的項(xiàng)目的特點(diǎn): 模塊化, 組件化, 工程化
6.1.2 創(chuàng)建項(xiàng)目并啟動(dòng)
第一步,全局安裝:npm i -g create-react-app
第二步,切換到想創(chuàng)項(xiàng)目的目錄,使用命令:create-react-app hello-react
第三步,進(jìn)入項(xiàng)目文件夾:cd hello-react
第四步,啟動(dòng)項(xiàng)目:npm start
6.1.3 react腳手架項(xiàng)目結(jié)構(gòu)
public ---- 靜態(tài)資源文件夾
? favicon.icon ------ 網(wǎng)站頁簽圖標(biāo)(一定要是icon格式)
? index.html -------- 主頁面(整個(gè)項(xiàng)目只有這一個(gè)html文件,SPA應(yīng)用,即單頁面應(yīng)用)
? logo192.png ------- logo圖
? logo512.png ------- logo圖
? manifest.json ----- 應(yīng)用加殼的配置文件
? robots.txt -------- 爬蟲協(xié)議文件
src ---- 源碼文件夾
? App.css -------- App組件的樣式
? App.js --------- App 組件
? App.test.js ---- 用于給App做測試(幾乎不用)
? index.css ------ 樣式
? index.js ------- 入口文件
? logo.svg ------- logo圖
? reportWebVitals.js
? — 頁面性能分析文件(需要web-vitals庫的支持)
? setupTests.js
? ---- 組件單元測試的文件(需要jest-dom庫的支持)
6.1.4 功能界面的組件化編碼流程(通用)
拆分組件: 拆分界面,抽取組件
實(shí)現(xiàn)靜態(tài)組件: 使用組件實(shí)現(xiàn)靜態(tài)頁面效果
實(shí)現(xiàn)動(dòng)態(tài)組件
? 3.1 動(dòng)態(tài)顯示初始化數(shù)據(jù)
? 3.1.1 數(shù)據(jù)類型
? 3.1.2 數(shù)據(jù)名稱
? 3.1.3 保存在哪個(gè)組件?
? 3.2 交互(從綁定事件監(jiān)聽開始)
6.2 react ajax
6.2.1 理解
-
React本身只關(guān)注于界面, 并不包含發(fā)送ajax請求的代碼
-
前端應(yīng)用需要通過ajax請求與后臺進(jìn)行交互(json數(shù)據(jù))
-
react應(yīng)用中需要集成第三方ajax庫(或自己封裝)
-
Query: 比較重, 如果需要另外引入不建議使用
-
axios: 輕量級, 建議使用
? 1) 封裝XmlHttpRequest對象的ajax
? 2) promise風(fēng)格
? 3) 可以用在瀏覽器端和node服務(wù)器端
6.2.2 axios
-
GET請求
axios.get('/user?ID=12345').then(function (response) {console.log(response.data);}).catch(function (error) {console.log(error);});
axios.get(’/user’, {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
-
POST請求
axios.post('/user', {firstName: 'Fred',lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); }); -
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
6.2.3 react腳手架配置代理總結(jié)
-
方法1
? 在package.json中追加如下配置
"proxy":"http://localhost:5000"- 1
? 說明:
? 1)優(yōu)點(diǎn):配置簡單,前端請求資源時(shí)可以不加任何前綴。
? 2)缺點(diǎn):不能配置多個(gè)代理。
? 3)工作方式:上述方式配置代理,當(dāng)請求了3000不存在的資源時(shí),那么該請求會轉(zhuǎn)發(fā)給5000 (優(yōu)先匹配前端資源)
-
方法2:
? 1)第一步:創(chuàng)建代理配置文件
? 在src下創(chuàng)建配置文件:src/setupProxy.js
? 2) 編寫setupProxy.js配置具體代理規(guī)則:
const proxy = require('http-proxy-middleware') - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 優(yōu)點(diǎn):可以配置多個(gè)代理,可以靈活的控制請求是否走代理。
- 缺點(diǎn):配置繁瑣,前端請求資源時(shí)必須加前綴。
-
工具庫: PubSubJS
-
下載: npm install pubsub-js --save
-
使用:
? 1) import PubSub from ‘pubsub-js’ //引入
? 2) PubSub.subscribe(‘delete’, function(data){ }); //訂閱
? 3) PubSub.publish(‘delete’, data) //發(fā)布消息
-
理解
? 1)先訂閱,再發(fā)布(理解:有一種隔空對話的感覺)
? 2)適用于任意組件間通信
-
文檔
1) https://github.github.io/fetch/
2) https://segmentfault.com/a/1190000003810652
-
特點(diǎn)
1)fetch: 原生函數(shù),不再使用XmlHttpRequest對象提交ajax請求(axios和jQuery都是對XmlHttpRequset的封裝)
2)老版本瀏覽器可能不支持
-
相關(guān)API
1)GET請求
fetch(url).then(function(response) {return response.json()}).then(function(data) {console.log(data)}).catch(function(e) {console.log(e)}); - 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
-
單頁Web應(yīng)用(single page web application,SPA)。
-
整個(gè)應(yīng)用只有==一個(gè)完整的頁面==。
-
點(diǎn)擊頁面中的鏈接==不會刷新頁面,只會做頁面的局部更新。==
-
數(shù)據(jù)都需要通過ajax請求獲取, 并在前端異步展現(xiàn)。
-
一個(gè)路由就是一個(gè)映射關(guān)系(key:value)
-
key為路徑, value可能是function或component
-
理解: value是function, 用來處理客戶端提交的請求。
-
注冊路由: router.get(path, function(req, res))
-
工作過程:當(dāng)node接收到一個(gè)請求時(shí), 根據(jù)請求路徑找到匹配的路由, 調(diào)用路由中的函數(shù)來處理請求, 返回響應(yīng)數(shù)據(jù)
-
瀏覽器端路由,value是component,用于展示頁面內(nèi)容。
-
注冊路由:
-
工作過程:當(dāng)瀏覽器的path變?yōu)?test時(shí), 當(dāng)前路由組件就會變?yōu)門est組件
-
react的一個(gè)插件庫。
-
專門用來實(shí)現(xiàn)一個(gè)SPA應(yīng)用。
-
基于react的項(xiàng)目基本都會用到此庫。
-
< BrowserRouter >
-
< HashRouter >
-
< Route >
-
< Redirect >
-
< Link >
-
< NavLink >
-
< Switch >
-
history對象
-
match對象
-
withRouter函數(shù)
module.exports = function(app) {
app.use(
proxy(’/api1’, { //api1是需要轉(zhuǎn)發(fā)的請求(所有帶有/api1前綴的請求都會轉(zhuǎn)發(fā)給5000)
target: ‘http://localhost:5000’, //配置轉(zhuǎn)發(fā)目標(biāo)地址(能返回?cái)?shù)據(jù)的服務(wù)器地址)
changeOrigin: true, //控制服務(wù)器接收到的請求頭中host字段的值
/*
changeOrigin設(shè)置為true時(shí),服務(wù)器收到的請求頭中的host為:localhost:5000
changeOrigin設(shè)置為false時(shí),服務(wù)器收到的請求頭中的host為:localhost:3000
changeOrigin默認(rèn)值為false,但我們一般將changeOrigin值設(shè)為true
*/
pathRewrite: {’^/api1’: ‘’} //去除請求前綴,保證交給后臺服務(wù)器的是正常請求地址(必須配置)
}),
proxy(’/api2’, {
target: ‘http://localhost:5001’,
changeOrigin: true,
pathRewrite: {’^/api2’: ‘’}
})
)
}
? 說明:
6.2.4 消息訂閱-發(fā)布機(jī)制
? 3)要在組件的componentWillUnmount中取消訂閱
6.2.5 擴(kuò)展:Fetch(關(guān)注分離思想)
2)POST請求
fetch(url, {method: "POST",body: JSON.stringify(data),}).then(function(data) {console.log(data)}).catch(function(e) {console.log(e)})7 React路由
7.1 相關(guān)理解
7.1.1 SPA 的理解
7.1.2 路由的理解
1. 什么是路由?
2. 路由分類
? 1) 后端路由:
? 2) 前端路由:
7.1 .3 react-router-dom的理解
7.2 react-router-dom相關(guān)API
7.2.1 內(nèi)置組件
7.2.2. 其它
8 代碼
里面由筆記的markdown版本和源代碼,還有一些其他的學(xué)習(xí)筆記
GitHub地址
9 參考
尚硅谷React全家桶
ps:張?zhí)煊砝蠋熤v得超級棒,yysd
總結(jié)
- 上一篇: 马云:大数据时代_最重要的是做最好的自己
- 下一篇: 笔记本电脑如何选购并安装内存条