1.定義組件
1.1函數(shù)式組件
function MyComponent(){
console.log(this); //此處的this是undefined,因?yàn)閎abel編譯后開(kāi)啟了嚴(yán)格模式
return <h2>我是用函數(shù)定義的組件</h2>
}
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
1.2類式組件
class MyComponent extends React.Component{
render(){
//render是放在哪里的?—— MyComponent的原型對(duì)象上,供實(shí)例使用。
//render中的this是誰(shuí)?—— MyComponent的實(shí)例對(duì)象 <=> MyComponent組件實(shí)例對(duì)象。
console.log('render中的this:',this);
return <h2>我是用類定義的組件</h2>
}
}
ReactDOM.render(<MyComponent/>,document.getElementById('test'))
注意
- 類式組件沒(méi)有state,
- 引入組件要使用大寫(xiě)
- 組件要大寫(xiě)
- 執(zhí)行類式組件過(guò)程:
1.React解析組件標(biāo)簽,找到了MyComponent組件。
2.發(fā)現(xiàn)組件是使用類定義的,隨后new出來(lái)該類的實(shí)例,并通過(guò)該實(shí)例調(diào)用到原型上的render方法。
3.將render返回的虛擬DOM轉(zhuǎn)為真實(shí)DOM,隨后呈現(xiàn)在頁(yè)面中。 - 執(zhí)行函數(shù)式組件過(guò)程:
執(zhí)行了ReactDOM.render(<MyComponent/>.......之后,發(fā)生了什么?
1.React解析組件標(biāo)簽,找到了MyComponent組件。
2.發(fā)現(xiàn)組件是使用函數(shù)定義的,隨后調(diào)用該函數(shù),將返回的虛擬DOM轉(zhuǎn)為真實(shí)DOM,隨后呈現(xiàn)在頁(yè)面中。
2.組件三大屬性
2.1state
class Weather extends React.Component{
state = {isHot:true}
render(){
const {isHot} = this.state;
return <h2 onClick={this.demo}>今天天氣很{this.state.isHot?'炎熱':'涼爽'}</h2>
}
demo = ()=>{
const isHot = this.state.isHot;
this.setState({isHot:!isHot})
console.log(this);
}
}
ReactDOM.render(<Weather/>,document.getElementById('example'))
解釋:給h2綁定一個(gè)點(diǎn)擊事件,把這個(gè)函數(shù)放在原型上,當(dāng)點(diǎn)擊h2的時(shí)候,就順著原型鏈找到這個(gè)點(diǎn)擊函數(shù),賦值給onClick的回調(diào)函數(shù),點(diǎn)擊的時(shí)候調(diào)用這個(gè)點(diǎn)擊函數(shù)。但是這個(gè)時(shí)候執(zhí)行函數(shù),函數(shù)中的this指向的是undefined。因?yàn)檫@個(gè)點(diǎn)擊函數(shù)是類中定義的函數(shù),在局部是嚴(yán)格模式,是undefined,所以我們要解決這個(gè)問(wèn)題。
我們將這個(gè)點(diǎn)擊函數(shù)的this指向更改為實(shí)例對(duì)象,再賦值給實(shí)例對(duì)象,這是時(shí)候就在實(shí)例中創(chuàng)建了一個(gè)‘相同’的點(diǎn)擊函數(shù), 我們點(diǎn)擊h2時(shí)候的那個(gè)是原型上的那個(gè)點(diǎn)擊函數(shù)。這個(gè)時(shí)候就可以在點(diǎn)擊函數(shù)中通過(guò)this來(lái)改變state的狀態(tài)了
2.2props
class Person extends React.Component{
render() {
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>年齡:{age+1}</li>
<li>性別:{sex}</li>
</ul>
)
}
}
const p = {name:'rose',age:'30',sex:'女'}
// 因?yàn)橛衎abel和React在這里,所以標(biāo)簽里面能用...p展開(kāi)運(yùn)算符來(lái)復(fù)制對(duì)象。別的地方不能 使用
ReactDOM.render(<Person {...p}/>,document.getElementById('text3'))
解釋:父子組件中通訊:在父組件中通過(guò)<子組件 {...對(duì)象}/>將這個(gè)值傳過(guò)去傳到子組件的props中
限制傳值的類型,必傳型
- 引入props-types
- 在子組件中使用組件.propTypes和組件.defaultProps
class Person extends React.Component{
render() {
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>年齡:{age+1}</li>
<li>性別:{sex}</li>
</ul>
)
}
// 當(dāng)你設(shè)置了這個(gè)之后,當(dāng)創(chuàng)建組件就去看你的名字是不是字符串,是不是有內(nèi)容,當(dāng)然要引入prop_types包
Person.propTypes = {
name: PropTypes.string.isRequired,//限制name為字符串,且為必傳
age: PropTypes.number, //限制age為數(shù)字
sex: PropTypes.string.isRequired,//限制sex為字符串,且為必傳
speak: PropTypes.func //限制speak為函數(shù)
}
// 設(shè)置默認(rèn)值
Person.defaultProps = {
age:18,
sex:'不男不女'
}
}
const p = {name:'rose',age:'30',sex:'女'}
ReactDOM.render(<Person {...p}/>,document.getElementById('text3'))
類式組件使用props
function Person(props){
const {name,age,sex} = props;
return (
<ul>
<li>姓名:{name}</li>
<li>年齡:{age}</li>
<li>性別:{sex}</li>
</ul>
)
}
// 這回這里的限制不能寫(xiě)在里面,要寫(xiě)在外面
Person.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
sex: PropTypes.string.isRequired,
speak: PropTypes.func
}
Person.defaultProps = {
age:18,
sex:'不男不女'
}
const p = {name:'rose',age:30,sex:'女'}
ReactDOM.render(<Person {...p}/>,document.getElementById('text3'))
2.3refs
方法一:使用字符串
class Mycomponent extends React.Component{
showData = ()=>{
// 通過(guò)this.refs來(lái)獲取組件中標(biāo)簽寫(xiě)了ref = XXX的標(biāo)簽
const {input1} = this.refs;
console.log('我被點(diǎn)擊了');
alert(input1.value);
}
onblurData = ()=>{
const {input2} = this.refs;
alert(input2.value);
}
render(){
return (
// input1包的雙引號(hào),說(shuō)明是字符串,還有其他形式的
// 這種形式已經(jīng)過(guò)時(shí)了,因?yàn)樾实? <nav>
<input ref="input1" type="text" placeholder = '請(qǐng)輸入' />
<button onClick={this.showData}>點(diǎn)我提示左側(cè)數(shù)據(jù)</button>
<input ref="input2" onBlur={this.onblurData} type="text" placeholder="失去焦點(diǎn)跳出"/>
</nav>
)
}
}
ReactDOM.render(<Mycomponent />,document.getElementById('text'))
方法二:使用回調(diào)函數(shù)
class Mycomponent extends React.Component{
showData = ()=>{
// 這里是this(實(shí)例 )
const {input1} = this;
alert(input1.value);
}
onblurData = ()=>{
const {input2} = this;
alert(input2.value);
}
render(){
return(
// 通過(guò)回調(diào)函數(shù)的形式來(lái)書(shū)寫(xiě)ref
// 解釋:當(dāng)創(chuàng)建組件的時(shí)候調(diào)用render發(fā)現(xiàn),有一個(gè)回調(diào)函數(shù),會(huì)主動(dòng)給你調(diào)用,將當(dāng)前結(jié)點(diǎn)傳進(jìn)去
// 將結(jié)點(diǎn)賦值給當(dāng)前實(shí)例(this,箭頭函數(shù)中的this指向上面有this的那個(gè)this就是render的this就是實(shí)例)并取名叫input1(.input1)
// 將這個(gè)ref掛在了實(shí)例身上了
// 這個(gè)注釋屬實(shí)雞肋
<nav>
{ /*<input ref={(currentNode)=>{this.input1 = currentNode}} type="text" placeholder = '請(qǐng)輸入' />*/}
<input ref={currentNode => this.input1 = currentNode} type="text" placeholder = '請(qǐng)輸入' />
<button onClick={this.showData}>點(diǎn)我提示左側(cè)數(shù)據(jù)</button>
<input ref={c=>this.input2 = c} onBlur={this.onblurData} type="text" placeholder="失去焦點(diǎn)跳出"/>
</nav>
)
}
}
ReactDOM.render(< Mycomponent/>,document.getElementById('text'))
方法三:使用ref容器
class Mycomponent extends React.Component{
// 通過(guò)React.createRef調(diào)用能返回一個(gè)ref容器,該容器能存儲(chǔ)被ref標(biāo)識(shí)的節(jié)點(diǎn),
// 該容器一個(gè)節(jié)點(diǎn)只能用一個(gè)
myref = React.createRef()
myref2 = React.createRef()
showData = ()=>{
console.log(this.myref);
alert(this.myref.current.value);
}
onblurData = ()=>{
alert(this.myref2.current.value);
}
render(){
return(
// 1.點(diǎn)擊事件Click的C是大寫(xiě),因?yàn)椴皇窍駄s一樣操縱的是原生DOM,而是自定義(合成)事件 為了更高的兼容性
// 4.React中的事件是通過(guò)事件委托的形式來(lái)給最外層的元素處理的 為了高效
<nav>
<input ref={this.myref} type="text" placeholder = '請(qǐng)輸入' />
<button onClick={this.showData}>點(diǎn)我提示左側(cè)數(shù)據(jù)</button>
<input ref={this.myref2} onBlur={this.onblurData} type="text" placeholder="失去焦點(diǎn)跳出"/>
</nav>
)
}
}
ReactDOM.render(< Mycomponent/>,document.getElementById('text'))
當(dāng)我們要在事件函數(shù)中傳遞參數(shù)的時(shí)候要使用高階函數(shù) 合理化
class Login extends React.Component{
state = {
username:'',
password:''
}
// 所以我們要將這個(gè)函數(shù)的返回值為一個(gè)函數(shù)作為onChange的回調(diào)函數(shù)!!實(shí)在要夸一句妙啊
saveFormData = (datatype)=>{
return (e) => {
// 更妙的是這里,使用[]來(lái)讀對(duì)象下的屬性,我們一般情況都是使用對(duì)象.屬性
// 直接datatype就是將datatype這個(gè)屬性添加到state中,而不是將username等傳進(jìn)去
this.setState({[datatype]:e.target.value})
}
}
handleSubmit = (e) =>{
e.preventDefault();
}
render(){
return (
// 在這里面,用戶名,密碼都要調(diào)用函數(shù),當(dāng)還有郵箱,復(fù)選框,文本框等,太多了。所以我們onChange調(diào)用事件改變一下
// 在這里我們saveFormData后面不能加小括號(hào),因?yàn)榧恿诵±ㄌ?hào)的意思是:
// 將調(diào)用saveFormData這個(gè)函數(shù),username傳過(guò)去會(huì)被e接收,再將返回值交給onChange的回調(diào)函數(shù)
// 而我們想要的是將這個(gè)saveFormData函數(shù)作為onChange的回調(diào)函數(shù),當(dāng)改變的時(shí)候就調(diào)用
<form action="#" onSubmit = {this.handleSubmit}>
<input type="text" onChange={this.saveFormData('username')} placeholder="請(qǐng)輸入..." name="username" />
<input type="password" onChange={this.saveFormData('password')} placeholder="請(qǐng)輸入..." name="password" />
<button>提交</button>
</form>
)
}
}
ReactDOM.render(<Login/>,document.getElementById('text'))
</script>
解釋:
高階函數(shù):符合下面其中一個(gè)就是高階函數(shù)
1.傳入的參數(shù)是函數(shù)
2.返回的是一個(gè)參數(shù)
我們這里的saveFormData就是一個(gè)高階函數(shù)
還有Promise setTimeOut map set filter 等等
函數(shù)的柯里化:通過(guò)函數(shù)調(diào)用的方式繼續(xù)返回函數(shù)的方式,實(shí)現(xiàn)多次接收參數(shù)最后統(tǒng)一處理
比如這里的saveFormData:先將username傳進(jìn)來(lái),調(diào)用那個(gè)箭頭函數(shù),將e傳進(jìn)來(lái),當(dāng)username和e兩個(gè)
參數(shù)都傳進(jìn)來(lái)后同意進(jìn)行處理。
function sum(a){
ruturn (b)=>{
return (c)=>{
return a+b+c
}
}
}
const result = sum(1)(2)(3)
console.log(result)
3.生命周期
我們之前在講類式組件和函數(shù)式組件的時(shí)候講了兩個(gè)的執(zhí)行過(guò)程
- 執(zhí)行類式組件過(guò)程:
1.React解析組件標(biāo)簽,找到了MyComponent組件。
2.發(fā)現(xiàn)組件是使用類定義的,隨后new出來(lái)該類的實(shí)例,并通過(guò)該實(shí)例調(diào)用到原型上的render方法。
3.將render返回的虛擬DOM轉(zhuǎn)為真實(shí)DOM,隨后呈現(xiàn)在頁(yè)面中。
...
但是當(dāng)我們new出該實(shí)例到呈現(xiàn)到頁(yè)面上組件經(jīng)歷了許多的過(guò)程
初始化階段: 由ReactDOM.render()觸發(fā)---初次渲染
1.constructor()
2.在更新之前獲取快照----getDerivedStateFromProps
3.render()
4.組件掛載完畢的鉤子----componentDidMount() =====> 常用
一般在這個(gè)鉤子中做一些初始化的事,例如:開(kāi)啟定時(shí)器、發(fā)送網(wǎng)絡(luò)請(qǐng)求、訂閱消息更新階段: 由組件內(nèi)部this.setSate()或父組件重新render觸發(fā)
1.getDerivedStateFromProps
2.控制組件更新的“閥門(mén)”----shouldComponentUpdate() 返回值為true才進(jìn)行下去
3.render()
4.getSnapshotBeforeUpdate
5.組件更新完畢的鉤子----componentDidUpdate(preProps,preState,snapshotValue) =====> 常用卸載組件: 由ReactDOM.unmountComponentAtNode()觸發(fā)
1.組件將要卸載的鉤子-----componentWillUnmount() =====> 常用
一般在這個(gè)鉤子中做一些收尾的事,例如:關(guān)閉定時(shí)器、取消訂閱消息
4.diff算法
1). react/vue中的key有什么作用?(key的內(nèi)部原理是什么?)
2). 為什么遍歷列表時(shí),key最好不要用index?
1. 虛擬DOM中key的作用:
1). 簡(jiǎn)單的說(shuō): key是虛擬DOM對(duì)象的標(biāo)識(shí), 在更新顯示時(shí)key起著極其重要的作用。
2). 詳細(xì)的說(shuō): 當(dāng)狀態(tài)中的數(shù)據(jù)發(fā)生變化時(shí),react會(huì)根據(jù)【新數(shù)據(jù)】生成【新的虛擬DOM】,
隨后React進(jìn)行【新虛擬DOM】與【舊虛擬DOM】的diff比較,比較規(guī)則如下:
a. 舊虛擬DOM中找到了與新虛擬DOM相同的key:
(1).若虛擬DOM中內(nèi)容沒(méi)變, 直接使用之前的真實(shí)DOM
(2).若虛擬DOM中內(nèi)容變了, 則生成新的真實(shí)DOM,隨后替換掉頁(yè)面中之前的真實(shí)DOM
b. 舊虛擬DOM中未找到與新虛擬DOM相同的key
根據(jù)數(shù)據(jù)創(chuàng)建新的真實(shí)DOM,隨后渲染到到頁(yè)面
2. 用index作為key可能會(huì)引發(fā)的問(wèn)題:
1. 若對(duì)數(shù)據(jù)進(jìn)行:逆序添加、逆序刪除等破壞順序操作:
會(huì)產(chǎn)生沒(méi)有必要的真實(shí)DOM更新 ==> 界面效果沒(méi)問(wèn)題, 但效率低。
2. 如果結(jié)構(gòu)中還包含輸入類的DOM:
會(huì)產(chǎn)生錯(cuò)誤DOM更新 ==> 界面有問(wèn)題。
3. 注意!如果不存在對(duì)數(shù)據(jù)的逆序添加、逆序刪除等破壞順序操作,
僅用于渲染列表用于展示,使用index作為key是沒(méi)有問(wèn)題的。
3. 開(kāi)發(fā)中如何選擇key?:
1.最好使用每條數(shù)據(jù)的唯一標(biāo)識(shí)作為key, 比如id、手機(jī)號(hào)、身份證號(hào)、學(xué)號(hào)等唯一值。
2.如果確定只是簡(jiǎn)單的展示數(shù)據(jù),用index也是可以的。
慢動(dòng)作回放----使用index索引值作為key
初始數(shù)據(jù):
{id:1,name:'小張',age:18},
{id:2,name:'小李',age:19},
初始的虛擬DOM:
<li key=0>小張---18<input type="text"/></li>
<li key=1>小李---19<input type="text"/></li>
更新后的數(shù)據(jù):
{id:3,name:'小王',age:20},
{id:1,name:'小張',age:18},
{id:2,name:'小李',age:19},
更新數(shù)據(jù)后的虛擬DOM:
<li key=0>小王---20<input type="text"/></li>
<li key=1>小張---18<input type="text"/></li>
<li key=2>小李---19<input type="text"/></li>
-----------------------------------------------------------------
慢動(dòng)作回放----使用id唯一標(biāo)識(shí)作為key
初始數(shù)據(jù):
{id:1,name:'小張',age:18},
{id:2,name:'小李',age:19},
初始的虛擬DOM:
<li key=1>小張---18<input type="text"/></li>
<li key=2>小李---19<input type="text"/></li>
更新后的數(shù)據(jù):
{id:3,name:'小王',age:20},
{id:1,name:'小張',age:18},
{id:2,name:'小李',age:19},
更新數(shù)據(jù)后的虛擬DOM:
<li key=3>小王---20<input type="text"/></li>
<li key=1>小張---18<input type="text"/></li>
<li key=2>小李---19<input type="text"/></li>
案例
class Person extends React.Component{
state = {
persons:[
{id:1,name:'小張',age:18},
{id:2,name:'小李',age:19},
]
}
add = ()=>{
const {persons} = this.state
const p = {id:persons.length+1,name:'小王',age:20}
this.setState({persons:[p,...persons]})
}
render(){
return (
<div>
<h2>展示人員信息</h2>
<button onClick={this.add}>添加一個(gè)小王</button>
<h3>使用index(索引值)作為key</h3>
<ul>
{
this.state.persons.map((personObj,index)=>{
return <li key={index}>{personObj.name}---{personObj.age}<input type="text"/></li>
})
}
</ul>
<hr/>
<hr/>
<h3>使用id(數(shù)據(jù)的唯一標(biāo)識(shí))作為key</h3>
<ul>
{
this.state.persons.map((personObj)=>{
return <li key={personObj.id}>{personObj.name}---{personObj.age}<input type="text"/></li>
})
}
</ul>
</div>
)
}
}
ReactDOM.render(<Person/>,document.getElementById('test'))
總結(jié):最好數(shù)據(jù)中要有唯一確定的值來(lái)確定這個(gè)標(biāo)識(shí)
5.腳手架
(這里使用的是v5的)
5.1如何開(kāi)啟腳手架
- 安裝
npm i -g create-react-app 為創(chuàng)建react項(xiàng)目腳手架庫(kù) - 創(chuàng)建
create-react-app 項(xiàng)目名 - 啟動(dòng)
npm start
項(xiàng)目的整體技術(shù)架構(gòu)為: react + webpack + es6 + eslint
5.2react項(xiàng)目?jī)?nèi)容介紹
public ---- 靜態(tài)資源文件夾
favicon.icon ------ 網(wǎng)站頁(yè)簽圖標(biāo)
index.html -------- 主頁(yè)面
logo192.png ------- logo圖
logo512.png ------- logo圖
manifest.json ----- 應(yīng)用加殼的配置文件
robots.txt -------- 爬蟲(chóng)協(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ù)的支持)
5.3父子組件之間互傳數(shù)據(jù)
一層層的傳
- 我們一般在src中創(chuàng)建組件components
- 可以將.js寫(xiě)為.jsx
- 下載ES7-react插件,使用rcc創(chuàng)建類式組件,rfc創(chuàng)建函數(shù)式組件
- 在v5中一般使用類式組件,因?yàn)楦缸又g能通過(guò)props來(lái)傳數(shù)據(jù)
- 狀態(tài)在哪里,操作狀態(tài)的方法就在哪里
- 子傳夫數(shù)據(jù):在父中定義函數(shù),<子組件 函數(shù)={this.函數(shù)}/>,然后在子組件中調(diào)用函數(shù)(函數(shù)在this.props中),就能將數(shù)據(jù)傳到父組件
- 遍歷數(shù)組使用map((pre,now)=>{})
- 解構(gòu)+重命名
let obj = {a:{b:1}}
const {a} = obj; //傳統(tǒng)解構(gòu)賦值
const {a:} = obj; //連續(xù)解構(gòu)賦值
const {a:{b:value}} = obj; //連續(xù)解構(gòu)賦值+重命名 - 通過(guò)let newList = [dolistObj,...dolist]來(lái)將dolistObj追加到dolist的第一行
關(guān)系老遠(yuǎn)組件之間傳
使用PubSub
1.下載 npm install pubsub-js --save
2.引入:import PubSub from 'pubsub-js'
3.使用:
在需要數(shù)據(jù)的組件中
componentDidMount(){
// 訂閱一個(gè)MY TOPIC
//{isFirst:false,isLoading:true}這個(gè)數(shù)據(jù)對(duì)象能被stateObj接收
var token = PubSub.subscribe('MY TOPIC', (_,stateObj)=>{
this.setState(stateObj)
})
}
componentWillMount(){
// 在渲染組件之后取消訂閱
PubSub.unsubscribe(this.token)
}
在傳遞數(shù)據(jù)的組件中
// 發(fā)布這個(gè)MY TOPIC,傳遞數(shù)據(jù)
PubSub.publish('MY TOPIC',{isFirst:false,isLoading:true});
原理就是能夠發(fā)現(xiàn)這個(gè)MY TOPIC,并檢測(cè)
5.4axios
前提:
- React本身只關(guān)注于界面, 并不包含發(fā)送ajax請(qǐng)求的代碼
- 前端應(yīng)用需要通過(guò)ajax請(qǐng)求與后臺(tái)進(jìn)行交互(json數(shù)據(jù))
- react應(yīng)用中需要集成第三方ajax庫(kù)(或自己封裝)
所以使用axios
使用:
- 下載 npm i axios
- 引入 import axios from 'axios'
- 使用:
axios.get('http://localhost:5000/students').then(
response => {console.log('成功了',response.data);},
error => {console.log('失敗了',error);}
)
但是我們現(xiàn)在是3000的本地要去請(qǐng)求來(lái)自5000的數(shù)據(jù),存在跨域問(wèn)題。解決辦法:react腳手架配置代理
方法一:
在package.json中追加如下配置
"proxy":"http://localhost:5000"
說(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)先匹配前端資源)
方法二
-
第一步:創(chuàng)建代理配置文件
在src下創(chuàng)建配置文件:src/setupProxy.js -
編寫(xiě)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:5000 changeOrigin設(shè)置為false時(shí),服務(wù)器收到的請(qǐng)求頭中的host為:localhost:3000 changeOrigin默認(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': ''} }) ) }
說(shuō)明:
- 優(yōu)點(diǎn):可以配置多個(gè)代理,可以靈活的控制請(qǐng)求是否走代理。
- 缺點(diǎn):配置繁瑣,前端請(qǐng)求資源時(shí)必須加前綴。
項(xiàng)目
export default class Search extends Component {
search = ()=>{
//獲取用戶的輸入(連續(xù)解構(gòu)賦值+重命名)
const {keyWordElement:{value:keyWord}} = this
//發(fā)送請(qǐng)求前通知App更新?tīng)顟B(tài)
this.props.updateAppState({isFirst:false,isLoading:true})
//發(fā)送網(wǎng)絡(luò)請(qǐng)求
axios.get(`/api1/search/users?q=${keyWord}`).then(
response => {
//請(qǐng)求成功后通知App更新?tīng)顟B(tài)
this.props.updateAppState({isLoading:false,users:response.data.items})
},
error => {
//請(qǐng)求失敗后通知App更新?tīng)顟B(tài)
this.props.updateAppState({isLoading:false,err:error.message})
}
)
//發(fā)送網(wǎng)絡(luò)請(qǐng)求---使用fetch發(fā)送(優(yōu)化)
try {
const response= await fetch(`/api1/search/users?q=${keyWord}`)
const data = await response.json()
console.log(data);
PubSub.publish('atguigu',{isLoading:false,users:data.items})
} catch (error) {
console.log('請(qǐng)求出錯(cuò)',error);
PubSub.publish('atguigu',{isLoading:false,err:error.message})
}
}
}
render() {
return (
<section className="jumbotron">
<h3 className="jumbotron-heading">搜索github用戶</h3>
<div>
<input ref={c => this.keyWordElement = c} type="text" placeholder="輸入關(guān)鍵詞點(diǎn)擊搜索"/>
<button onClick={this.search}>搜索</button>
</div>
</section>
)
}
}
6.路由
redux
- 有啥用?當(dāng)多個(gè)組件要共享一個(gè)狀態(tài)數(shù)據(jù)的時(shí)候,我們將這個(gè)數(shù)據(jù)放在redux中,那個(gè)組件需要就去redux中取
-
原理是啥?
redux原理圖.png
解釋下:就是我需要數(shù)據(jù)的那個(gè)組件調(diào)用action的函數(shù),
- 怎么用?
- 在src下創(chuàng)建一個(gè)redux再在下面創(chuàng)建store reductor action
