React 類組件和函數(shù)組件

組件(Component)

1、組件:能跟其他物件組合起來(lái)的物件
2、就目前而言,一個(gè)返回React元素的“函數(shù)”就是組件
3、在Vue里,一個(gè)構(gòu)造選項(xiàng)就可以表示一個(gè)組件

元素與組件
元素:const div = React.createElement('div',...)
//這是一個(gè)React元素(d是小寫(xiě)的)
組件:const Div = ()=>React.createElement('div'..)
//這是一個(gè)React組件(D是大寫(xiě)的)

React 的兩種組件

1、類組件

class Son extends React.Component {
  constructor() {
    super();
    this.state = {
      n: 0
    };
  }

  add() {
    this.setState({ n: this.state.n + 1 });
  }

  render() {
    return (
      <div className="Son">
        兒子n :{this.state.n}
        <button onClick={() => this.add()}>+1</button>
        <Grandson />
      </div>
    );
  }
}

類組件注意事項(xiàng):

  • this.state.n += 1 無(wú)效?
    //其實(shí)n已經(jīng)變了,UI沒(méi)自動(dòng)更新,
    //調(diào)用 setState 才會(huì)觸發(fā)更新(異步更新,這里復(fù)制原有n,得到一個(gè)新的n)
    //React不不像Vue一直監(jiān)聽(tīng)data 所以不會(huì)更新
  • setState 會(huì)異步更新UI
    //setState 之后,state不會(huì)立馬改變,立馬讀會(huì)失敗
    //推薦使用setState(函數(shù))

2、函數(shù)組件

const Grandson = () => {
  const [n, setN] = React.useState(0);
  return (
    <div className="Grandson">
      孫子n:{n}
      <button onClick={() => setN(n + 1)}>+1</button>
    </div>
  );
};

函數(shù)組件注意事項(xiàng):
沒(méi)有 this,一律使用參數(shù)和變量

組件使用方法:

  • <Welcome />會(huì)被翻譯成什么

  • <div />會(huì)被翻譯為React.createElement('div')

  • <Welcome />翻譯為React.createElement(Welcome)

  • 可以用babel online直接翻譯給你看

  • React.createElement的邏輯

  • 如果傳入一個(gè)字符串div, 則會(huì)創(chuàng)建div

  • 如果傳入一個(gè)函數(shù),則會(huì)調(diào)用該函數(shù),獲取其返回值

  • 如果傳入一個(gè)類,則在類前面加個(gè)new(這會(huì)導(dǎo)致執(zhí)行constructor), 獲取一個(gè)組件對(duì)象,然后調(diào)用對(duì)象的render方法,獲取其返回值

props - 外部數(shù)據(jù)

const root =document.getElementById('root')
const React = window.React
const ReactDOM = window.ReactDOM
// import React from 'react'
// import ReactDOM from 'react-dom'

function App(){
  return(
    <div className="App">
      爸爸
      <Son x="吃飯"/>
    </div>
  )
}

class Son extends React.Component{
  constructor(){
    super()
    this.state = {
      n:0
    }
  }
  add(){
    this.setState({n:this.state.n+1})
  }
  render(){
    return(
      <div>
        兒子 n:{this.state.n},{this.props.x} //---------類組件直接用this.props接收值
        <button onClick={()=>this.add()}> +1 </button>
        <Grandson y="睡覺(jué)"/>
      </div>
    )
  }
}

const Grandson =(props) =>{
  const [n,setN] = React.useState(0)
  return(
    <div>
      孫子 n:{n},{props.x}//---------函數(shù)組件接收一個(gè)props的參數(shù)不需要this就可以接收值
      <button onClick={()=>setN(n+1)}> +1 </button>
    </div>
  )
}
ReactDOM.render(App(),root);

state - 內(nèi)部數(shù)據(jù)

  • 鏈接
  • 類組件用this.state讀,this.setState寫(xiě)
  • 函數(shù)組件用useState返回?cái)?shù)組,第一項(xiàng)讀,第二項(xiàng)寫(xiě)
  • 關(guān)注數(shù)據(jù)的時(shí)候我們需要關(guān)注,初始化,怎么讀,怎么寫(xiě)
  • 直接改state的n,ui不會(huì)刷新,vue里面是對(duì)data做了劫持,必須要用setState,
  • 另外不推薦對(duì)象局部改變了,又原封不動(dòng)的給setState,效果是ok的但是一般推薦要產(chǎn)生一個(gè)新的對(duì)象
  • 這就叫做數(shù)據(jù)不可變,以前的數(shù)據(jù)不要改,要改就產(chǎn)生一個(gè)新的對(duì)象
    this.setState({ n: this.state.n + 1 });
  • 牛x的前端用setState(函數(shù)),這樣寫(xiě)的好處,打印n的值發(fā)現(xiàn)不對(duì),因?yàn)閟etState是異步的更新ui的過(guò)程,好處就是避免異步造成的誤解
this.setState((state)=>{
  return {n: state.n+1}
})

// 如果用這種寫(xiě)法就很清楚的知道舊的state和新的state
// 打印n
this.setState(state=>{
  const n = state.n + 1
  console.log(n)
  return {n}
})

setState 注意事項(xiàng)

  • this.state.n += 1無(wú)效?
  • 其實(shí)n已經(jīng)改變了,只不過(guò)UI不會(huì)自動(dòng)更新而已
  • 調(diào)用setState才會(huì)觸發(fā)UI更新(異步更新)
  • 因?yàn)镽eact沒(méi)有像Vue監(jiān)聽(tīng)data一樣監(jiān)聽(tīng)state
  • setState會(huì)異步更新UI
  • setState之后,state不會(huì)馬上改變,立馬讀state會(huì)失敗
  • 更推薦的方式是setState(函數(shù)),函數(shù)接受一個(gè)舊的state返回一個(gè)新的state
  • this.setState(this.state)不推薦
  • React希望我們不要修改舊state(不可變數(shù)據(jù))
  • 常用代碼: setState({n: state.n + 1})
  • 總結(jié),這是一種理念(函數(shù)式)
函數(shù)組件注意事項(xiàng)
  • 跟類組件類似的地方,也要通過(guò)setX(新值)來(lái)更新UI
  • 跟類組件不同的地方,沒(méi)有this,一律用參數(shù)和變量

復(fù)雜的state

總結(jié)復(fù)雜的state

事件綁定

類組件的事件綁定

<button onClick={() => this.addN()}>n + 1</button>
// 傳一個(gè)函數(shù)給onClick即可,注意C大寫(xiě)
// 思考一個(gè)問(wèn)題,下面這樣寫(xiě)行不行
<button onClick={this.addN}>n + 1</button>
// 有問(wèn)題,這樣使得this.addN里的this變成window
<button onClick={this.addN.bind(this)}>n+1</button>
// 這樣寫(xiě)是可以的,因?yàn)樗祷匾粋€(gè)綁定了當(dāng)前this的新函數(shù)
// 但是這樣寫(xiě)太麻煩,你不如第一種
// 但是第一種寫(xiě)法依然太長(zhǎng),可用this._addN = ()=> this.addN()
// 給箭頭函數(shù)取個(gè)名字,然后寫(xiě)成,在構(gòu)造函數(shù)中賦值
<button onClick={this._addN}>n+1</button>
// 給箭頭函數(shù)取個(gè)名字,然后寫(xiě)成
<button onClick={this._addN}>n + 1</button>
// 這樣又不如寫(xiě)成
constructor() {
  this.addN = ()=> this.setState({n: this.state.n + 1})
}
render(){
  return <button onClick={this.addN}>n + 1</button>
}

但這樣寫(xiě)不如聲明addN結(jié)構(gòu)清晰
最終的方案,類組件的事件綁定最好的方法

class Son extends React.Component {
  addN = () => this.setState({n: this.state.n + 1});
  render() {
    return <button onClick={this.addN}>n+1</button>
  }
}
?著作權(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)容