react筆記

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

前提:

  1. React本身只關(guān)注于界面, 并不包含發(fā)送ajax請(qǐng)求的代碼
  2. 前端應(yīng)用需要通過(guò)ajax請(qǐng)求與后臺(tái)進(jìn)行交互(json數(shù)據(jù))
  3. 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ō)明:

  1. 優(yōu)點(diǎn):配置簡(jiǎn)單,前端請(qǐng)求資源時(shí)可以不加任何前綴。
  2. 缺點(diǎn):不能配置多個(gè)代理。
  3. 工作方式:上述方式配置代理,當(dāng)請(qǐng)求了3000不存在的資源時(shí),那么該請(qǐng)求會(huì)轉(zhuǎn)發(fā)給5000 (優(yōu)先匹配前端資源)
方法二
  1. 第一步:創(chuàng)建代理配置文件

    在src下創(chuàng)建配置文件:src/setupProxy.js
    
  2. 編寫(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ō)明:

  1. 優(yōu)點(diǎn):可以配置多個(gè)代理,可以靈活的控制請(qǐng)求是否走代理。
  2. 缺點(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)擊搜索"/>&nbsp;
                  <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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容