1. 程式人生 > >React——第三階段(1)(高階元件、context)

React——第三階段(1)(高階元件、context)

根據鬍子大哈的文章學習,感謝大胡分享
鬍子大哈-高階元件、context

高階元件

什麼是高階元件

高階元件就是一個函式,傳給他一個元件,他返回一個新的元件。這個新元件會使用傳入的元件作為其子元件。

高階元件體現的是——設計

核心思想:抽象具有相同需求邏輯的元件,用函式處理

例子:
可能有很多元件有這樣需求:“在元件掛載階段,從LocalStorage載入某欄位”
定義高階元件src/Component/wrapWithLoadData.js

import React, { Component } from 'react'

export default (WrappedComponent, name) => {
  class NewComponent extends Component {
    constructor () {
      super()
      this.state = { data: null }
    }

    componentWillMount () {
      let data = localStorage.getItem(name)
      this.setState({ data })
    }

    render () {
      return <WrappedComponent data={this.state.data} />
    }
  }
  return NewComponent
}

使用高階元件:

import wrapWithLoadData from './wrapWithLoadData'

class InputWithUserName extends Component {
  render () {
    return <input value={this.props.data} />
  }
}

InputWithUserName = wrapWithLoadData(InputWithUserName, 'username')
export default InputWithUserName

可以看到,InputWithUserName

元件,在內部其從LocalStorage 載入欄位的邏輯,直接是用的高階元件包裝。不用自己再寫了。

那麼高階元件的作用也就一目瞭然了:元件之間程式碼複用。
元件們可能有某些相似的邏輯,把這些邏輯抽象,做成高階元件,來達到複用效果。在高階元件內部,通過props把資料傳遞給被包裝的元件。

高階元件的靈活性

高階元件本質是裝飾者模式,通過組合方式,達到很高的靈活性。

比如,上邊的InputWithUserName不從LocalStorage載入,而是使用Ajax請求從伺服器載入。那麼,不需要修改元件邏輯,而是新寫一個wrapWithAjaxData的高階元件,然後包裝InputWithUserName

元件就可以了。

多層高階元件

兩個高階元件:wrapWithLoadData``wrapWithAjaxData
其中wrapWithAjaxData具體內容

...
      componentWillMount () {
        ajax.get('/data/' + this.props.data, (data) => {
          this.setState({ data })
      })    
...

我們的邏輯是,先從localStorage中拿到username,然後根據username從後臺拿到使用者的具體資料。
修改InputWithUserName

import wrapWithLoadData from './wrapWithLoadData'
import wrapWithAjaxData from './wrapWithAjaxData'

class InputWithUserName extends Component {
  render () {
    return <input value={this.props.data} />
  }
}

InputWithUserName = wrapWithAjaxData(InputWithUserName)
InputWithUserName = wrapWithLoadData(InputWithUserName, 'username')
export default InputWithUserName

React.js的context

全域性空間:父元件設定context並放入某狀態,其下每個孩子元件都可以從其取得狀態,而不用一層一層的向下傳遞。(更改了,就會重新渲染一遍)
爺爺元件是訪問不到context的。

寫法

static childContextTypes = {
  <key>: PropTypes.<型別>
}

getChildContext () {
  return {
    <key>: <value>
  }
}

childContextTypes:是為context中的欄位設定型別檢查,必須設定
getChildContext():用來設定元件的context
若在子元件要使用,可以寫

class Title extends Component {
  static contextTypes = {
    themeColor: PropTypes.string
  }

  render () {
    return (
      <h1 style={{ color: this.context.themeColor }}>React.js 小書標題</h1>
    )
  }

contextTypes首先要型別檢查,必須的
this.context.<key>即可獲取

總結

context打破了元件之間必須通過props傳遞狀態的過程,類似一個全域性變數空間,其內容能被隨意接觸修改。這樣導致程式不可控。

這種機制,對於狀態管理有很大幫助,redux-react就是充分利用了這個機制。

一般我們動手寫context,而是利用第三方狀態管理庫。

 



作者:布蕾布蕾
連結:https://www.jianshu.com/p/f05beebc12de
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。