小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

react 讀書(shū)筆記

 怡紅公子0526 2021-10-22

來(lái)源掘金小冊(cè) - react實(shí)戰(zhàn):設(shè)計(jì)模式和最佳實(shí)踐

react設(shè)計(jì)思想

  1. 屬性展開(kāi) - 保留當(dāng)前組件需要的props,并且使其他的props傳遞下去
  var obj = {a: 1, b: 2, c: 3, d: 4, e: 5}
  const { a, ...other } = obj
  console.log(other)  // {b: 2, c: 3, d: 4, e: 5}
  1. 在react中,界面完全由數(shù)據(jù)驅(qū)動(dòng)
  2. 在react中,一切都是組件
  3. props是react組件之間通訊的基本方式
  // 可以實(shí)現(xiàn)記錄用戶(hù)訪問(wèn)路徑操作信息,每次進(jìn)入某個(gè)頁(yè)面或者功能的時(shí)候都會(huì)訪問(wèn)一個(gè)線上資源
  // a.js
  export default Beacon extends React.Component {
    componentDidMount() {
      const beacon = new Image()
      beacon.src = 'https://age/i.png'
    }
    
    render() {
      return null
    }
  }
  // b.js
  render() {
    <div>
      <Beacon/>
    </div>
  }

  // 代碼組織方式優(yōu)化 - renderXXX函數(shù)訪問(wèn)的是同樣的props和state,代碼耦合嚴(yán)重
  class StopWatch extends React.Component {

    renderClock() {

    }

    renderButtons() {

    }

    renderSplitTimes() {

    }
    
    render() {
      const Clock = this.renderClock()
      const Buttons = this.renderButtons()
      const SplitTimes = this.renderSplitTimes()

      return (
        <div>
          {Clock}
          {Buttons}
          {SplitTimes}
        </div>
      )
    }
  }
  // 更好的組織方式
  class StopWatch extends React.Component {
    render() {
      return (
        <div>
          <Clock />
          <Buttons />
          <SplitTimes />
        </div>
      )
    }
  }
  const Clock = (props) = {

  }
  const Buttons = (props) => {

  }
  const SplitTimes = (props) => {

  }

設(shè)計(jì)react組件原則及最佳實(shí)踐

1. 保持接口小,props數(shù)量要少
2. 根據(jù)數(shù)據(jù)邊界來(lái)劃分組件,充分利用組合
3. 把state往上層組件提取,讓下層組件只需要實(shí)現(xiàn)為純函數(shù)
4. 避免renderXXXX函數(shù)
5. 給回調(diào)函數(shù)類(lèi)型的props加統(tǒng)一前綴,比如on or handle - onStart
6. 使用propTypes來(lái)定義組件的props
7. 盡量每個(gè)組件都有自己專(zhuān)屬的文件
8. 用解構(gòu)賦值的方式獲取參數(shù)props的屬性 - const { a, b } = { a: 1, b: 2 }
9. 利用屬性初始化來(lái)定義state和成員函數(shù) - 給默認(rèn)值 const { data = [] } = this.props
  /*
    1. 盡量不要在jsx中寫(xiě)內(nèi)聯(lián)函數(shù)
    2. 每次渲染,都會(huì)產(chǎn)生新的函數(shù)對(duì)象
    3. 每次傳給組件的props(方法,數(shù)據(jù),狀態(tài)等)都是新的,無(wú)法通過(guò)shouldComponentUpdate對(duì)props的檢查來(lái)避免重復(fù)渲染
  */
  <Buttons
    activated={this.state.isStarted}
    onStart={() => {/* TODO */}}
    onReset={() => {/* TODO */}}
  />
  /*
    1. style屬性的使用
    2. 內(nèi)聯(lián)樣式在組件每次渲染時(shí)都會(huì)創(chuàng)建一個(gè)新的style對(duì)象
    3. 如果樣式不發(fā)生改變,應(yīng)該把style對(duì)象提取到組件之外,可以重用一個(gè)對(duì)象
  */
  // bad
  const Clock = (props) => {
    return <h1 style={color: '#ccc'}>小姐姐真好看<h1/>
  }
  // good
  const style = {
    color: '#ccc'
  }
  const Clock = (props) => {
    return <h1 style={style}>小姐姐真好看<h1/>
  }

組件樣式

1. 不同組件中相同的元素樣式相互影響,a.js與b.js中都有h1組件,樣式之間會(huì)相互影響
2. 添加styled-jsx/styled-component支持
  // a.js
  index.css
  h1: {
    color: red
  }
  <h1>a</h1>
  // b.js
  <h1>b</h1>
  
  // a.js
  .a h1: {
    color: red
  }
  <div className='a'>
    <h1>a</h1>
  <div/>
  // b.js
  <div className='b'>
    <h1>a</h1>
  <div/>

狀態(tài)組件與無(wú)狀態(tài)組件分割

1. 軟件設(shè)計(jì)原則"責(zé)任分離",就是讓一個(gè)模塊責(zé)任盡量少,每個(gè)模塊專(zhuān)注于一個(gè)功能,有利于代碼的維護(hù)
2. react中數(shù)據(jù)渲染頁(yè)面,UI = f(data),但是盡量把獲取和管理數(shù)據(jù)與界面渲染分開(kāi),即把獲取數(shù)據(jù)與管理數(shù)據(jù)的邏輯放在父組件,把渲染界面的邏輯放在子組件
3. A組件渲染B組件時(shí),即使props傳入一樣,B組件也會(huì)完整走一遍渲染流程
4. 函數(shù)形式的react組件,好處是不需要管理state,占用資源少,但是函數(shù)組件無(wú)法利用shouldComponentUpdate來(lái)優(yōu)化減少渲染
5. PureComponent中實(shí)現(xiàn)的shouldComponentUpdate會(huì)對(duì)傳入的參數(shù)進(jìn)行淺比較,當(dāng)傳入的props為一個(gè)對(duì)象之類(lèi)的,比如由{a: 1, b: 2} => {a: 2, b: 2},可能會(huì)出現(xiàn)UI未更新的情況出現(xiàn)
6. shouldComponentUpdate函數(shù),每次渲染render函數(shù)之前會(huì)被調(diào)用,返回true繼續(xù)渲染,返回false立刻停止,可以對(duì)深層次的數(shù)據(jù)處理
7. 在使用PureComponent時(shí),盡量在render定義之外創(chuàng)建所有對(duì)象,數(shù)組和函數(shù),并確保在各種調(diào)用間,不發(fā)生更改 - 參考table例子
8. React.memo淺比較
  export default class A extends React.Component {
    state = {
      joke: null
    }

    componentDidMount() {
      fetch(url, {header: {'Accept': 'application/json'}})
        .then(res => {
          return res.json()
        })
        .then(json => {
          this.setState({joke: json.joke})
        })
    }

    render() {
      return <B value={this.state.joke} />
    }
  }

  export default class B extends React.Component {
    render() {
      return (
        <div>
          <img src={url} />
          {this.props.value || 'loading...'}
        </div>
      )
    }
  }
  <Table
    // map每次返回一個(gè)新數(shù)組,淺比較失敗
    rows={rows.map()}
    // 枚舉對(duì)象總不相同 - 盡量不寫(xiě)行內(nèi)樣式
    style={{color: '#ccc'}}
    // 箭頭函數(shù)每次都會(huì)重新渲染 - 組件層級(jí)不通過(guò)箭頭函數(shù)綁定事件
    onUpdate={() => {}}
  />

高階組件

待補(bǔ)充...

render props模式

1. render props的形式
2. render props其實(shí)就是依賴(lài)注入
3. 如何利用render props實(shí)現(xiàn)共享組件之間的邏輯
4. 依賴(lài)注入:**當(dāng)邏輯A依賴(lài)邏輯B時(shí),如果讓A直接依賴(lài)B,A做不到通用。依賴(lài)注入就是把B的邏輯以函數(shù)形式傳遞給A,讓A和B之間只需要對(duì)函數(shù)接口達(dá)成一致 - 組件A和B之間,不是把B組件寫(xiě)在A組件中,而是通過(guò)把B組件當(dāng)參數(shù)傳到A組件當(dāng)中**
  // 用戶(hù)登錄與未登錄情況下顯示不同的組件
  const Auth = (props) => {
    const userName = getUserName()
    if(userName) {
      const allProps = {userName, ...props}
      return (
        <React.Fragment>
          {props.login(allProps)}
        </React.Fragment>
      )
    } else {
      return (
        <React.Fragment>
          {props.noLogin(props)}
        </React.Fragment>
      )
    }
  }

  <Auth
    login={({userName}) => <h1>Hello {userName}</h1>}
    noLogin={() => <h1>Please login</h1>}
  />

提供者模式

1. 提供者模式,為了**解決組件間跨層級(jí)的信息傳遞**,A-B-C-D-...-X,當(dāng)數(shù)據(jù)要從A傳遞到X時(shí),通過(guò)props傳遞時(shí),會(huì)經(jīng)過(guò)B-C-D...,然而在B-C-D...中不需要使用props中的數(shù)據(jù),而且組件在變動(dòng)時(shí),容易出現(xiàn)props傳遞錯(cuò)誤的情況出現(xiàn)
2. 提供者模式,本質(zhì)由2個(gè)角色組成,一個(gè)叫'提供者’,一個(gè)叫'消費(fèi)者’,提供者(A)位于組件樹(shù)靠上的位置,消費(fèi)者(X)處于靠下的位置
3. 實(shí)現(xiàn)方式,通過(guò)**react提供的context功能進(jìn)行實(shí)現(xiàn)(v16.3.0+),context功能可以創(chuàng)造一個(gè)'上下文’,在這個(gè)上下文之中的所有組件都可以訪問(wèn)到同樣的數(shù)據(jù)**
4. 參考react-app中x2代碼

組合組件

1. 模式(Pattern) = 問(wèn)題場(chǎng)景(Context) + 解決方法(Solution)
2. 解決的問(wèn)題,**父組件想傳遞一些信息給子組件,但是通過(guò)props傳遞又很麻煩時(shí)**

組件狀態(tài)

1. UI = f(data),data = props + state,props代表外部傳進(jìn)來(lái)的數(shù)據(jù),state代表組件內(nèi)部狀態(tài)
2. 什么樣的數(shù)據(jù)可以存放在成員變量中?
3. 如果數(shù)據(jù)由外部傳入,放在props中
4. **如果是內(nèi)部組件數(shù)據(jù),這個(gè)數(shù)據(jù)的更改是否應(yīng)該立刻引發(fā)一次組件的重新渲染,如果是,放在state中,不是就放在成員變量中**
5. state不會(huì)被同步修改,在react的生命周期中或者處理函數(shù)中同步調(diào)用,setState不會(huì)立即同步state和重復(fù)渲染,但是如果setState由其他條件引發(fā),就有可能不是這樣了 - 在生命周期中或者事件函數(shù)中調(diào)用時(shí),react會(huì)打開(kāi)一個(gè)類(lèi)似標(biāo)記的東西,標(biāo)記打開(kāi)的過(guò)程中,setState調(diào)用都是往任務(wù)隊(duì)列里放任務(wù),當(dāng)函數(shù)調(diào)用結(jié)束時(shí),批量處理任務(wù)隊(duì)列,關(guān)閉標(biāo)記
6. 函數(shù)式setState -  當(dāng)setState的第一個(gè)參數(shù)為函數(shù)時(shí),任務(wù)列表上增加的就是一個(gè)可執(zhí)行的任務(wù)函數(shù),react沒(méi)處理完一個(gè)任務(wù),都會(huì)更新一次state,然后把新的state傳遞給這個(gè)任務(wù)函數(shù)
  // 代碼1
  class Foo extends Component {
    foo = 'foo'

    render() {
      return <div>{this.foo}</>
    }
  }
  // 代碼2
  this.state = {
    count: 0
  }

  this.setState({count: 1})
  console.log(this.state.count) // 0
  // 代碼3
  setTimeout(() => {
    this.setState({count: 2})
    console.log(this.state.count) // 2
  })
  // 代碼4 - 結(jié)果為1 三個(gè)任務(wù)都給了this.state.count一個(gè)值
  this.state = {
    count: 0
  }
  this.setState({count: this.state.count + 1})
  this.setState({count: this.state.count + 1})
  this.setState({count: this.state.count + 1})
  // 代碼5 - 函數(shù)式setState,結(jié)果為3
  // this.setState((preState, props) => ({})
  function increment(state, props) {
    return {count: state.count + 1}
  }
  this.state = {
    count: 0
  }
  this.setState(increment)
  this.setState(increment)
  this.setState(increment)

redux使用模式

1. 使用場(chǎng)景 - 復(fù)雜應(yīng)用下的狀態(tài)維護(hù),類(lèi)似于一個(gè)全局的store,**并且store只有接受某些'事件’(action),才可以修改store上的數(shù)據(jù),store對(duì)這些'事件’的響應(yīng),就是修改狀態(tài)(修改狀態(tài)的函數(shù)reducer)**
2. 事件(action) - 響應(yīng)函數(shù)(reducer) -store
3. 對(duì)于某個(gè)狀態(tài),是放在store中還是組件自身狀態(tài)中?
4. 看狀態(tài)是否會(huì)被多個(gè)react組件共享 - 不同級(jí)組件件的數(shù)據(jù)共享
5. 看這個(gè)組件被unmount之后重新被mount,之前的狀態(tài)是否需要保留 - 組件銷(xiāo)毀后又重新渲染,之前的輸入是否要保留
6. 代碼組織方式 - 基于角色分類(lèi)(modal,services,view,action,reducer)和基于功能分類(lèi)(安裝功能所在模塊分類(lèi))
7. connect函數(shù)接受兩個(gè)參數(shù),一個(gè)mapStateToProps是把Store上的state映射為props,另一個(gè)mapDispatchToProps是把回調(diào)函數(shù)類(lèi)型的props映射為派發(fā)action,connect函數(shù)調(diào)用會(huì)產(chǎn)生一個(gè)'高階組件’
8. react-redux中使用了三個(gè)模式 - 提供者模式,高階組件,有狀態(tài)組件和無(wú)狀態(tài)組件
  // 代碼1
  import { createStore } from 'redux'
  import { Provider } from 'react-redux'
  import store from './store'

  const store = createStore(store)

  <Provider store={store}>
    {Provider之下的所有組件都可以connect到給定的store}
  </Provider>
  // 代碼2
  const Button = ({count, onIncrement}) => {
    return (
      <div>
        <div>{count}</div>
        <button onClick={onIncrement}>+</button>
      </div>
    )
  }
  // 代碼3
  import { connect } from 'react-redux'

  const mapStateToProps = (state) => {
    return {
      count: count + 1
    }
  }

  const mapDispatchToProps = (dispatch) => {
    onIncrement: () => dispatch({type: 'INCREMENT'})
  }

  const Counter = connect(mapStateToProps, mapDispatchToProps)(Button)

mobx使用模式

待補(bǔ)充...

redux與mobx模式對(duì)比

待補(bǔ)充...

路由 react router

1. 單頁(yè)應(yīng)用 - 把URL映射到對(duì)應(yīng)的頁(yè)面來(lái)處理,頁(yè)面之間切換做到局部更新
2. 動(dòng)態(tài)路由 - 指的路由規(guī)則不是預(yù)先確定的,而是在渲染過(guò)程中確定的(React Router v4)
3. 靜態(tài)路由 - 路由規(guī)則是固定的

未完待續(xù)...

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多