对于 React 中 context 的理解

一、Context 的认识

  1. React 中,父子组件通信的机制,父子组件的通信是通过 props 进行数据的传递,如下所示:
  • 父组件向子组件传递数据(状态)时,是在调用子组件的时候通过参数传递给子组件,子组件通过 this.props 进行接收
  • 子组件如果更改父组件的一些属性,则是通过父组件定义的方法来传递给子组件,子组件调用更改
  • 如果父组件想要更改子组件的一些状态时,通过 ref 进行标记,可以获取子组件的所有信息,从而调用子组件的方法和值
  • 当层级很多时,使用 props 进行逐层的传递,是不行的,而 context 就可以解决
  1. context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。如果我们不想通过 props 实现组件树的逐层传递数据,则可以使用 context 实现跨层级进行数据传递。

  2. context api 给出三个概念:React.createContext()、Provider、Consumer,如下所示:

  • React.createContext(),这个方法用来创建 context 对象,并包含 Provider、Consumer两个组件 <Provider />、<Consumer />,也是创建一个上下文的容器(组件), defaultValue 可以设置共享的默认数据,如 const {Provider, Consumer} = React.createContext(defaultValue);
  • Provider,数据的生产者,通过 value 属性接收存储的公共状态,来传递给子组件或后代组件,如 <Provider value={/* some value */}>
  • Consumer,数据的消费者,通过订阅 Provider 传入的 context 的值,来实时更新当前组件的状态。Consumer 需要嵌套在生产者下面,才能通过回调的方式拿到共享的数据源,如
<Consumer>
  {value => /* render something based on the context value */}
</Consumer>
  1. 每当 Provider 的值发生改变时, 作为 Provider 后代的所有 Consumers 都会重新渲染。props 是单向数据流动,所以当 props 传递数据很繁琐,可以采用 context,进行跨组件传递数据。在最外层的组件上,通过生产者Provider 组件进行包裹,并存储共享数据到value 中,当然可以是任何数据类型。后带需要用到共享数据的组件均可通过 Consumer 进行数据获取。

  2. 对于 Reactcontext 的简单应用,代码如下所示:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>context</title>
</head>
<body>

<div id="test"></div>

<script type="text/javascript" src="./js/react.development.js"></script>
<script type="text/javascript" src="./js/react-dom.development.js"></script>
<script type="text/javascript" src="./js/prop-types.js"></script>
<script type="text/javascript" src="./js/babel.min.js"></script>

<script type="text/babel">
  class A extends React.Component {

    state = {
      color: 'red'
    }

    /*
    声明向后代组件传递的context中的数据
   */
    static childContextTypes = {
      color: PropTypes.string
    }

    /*
  给后代组件返回包含指定数据的context对象
   */
    getChildContext() {
      return {color: this.state.color};
    }

    render () {
      return (
        <div>
          <h2>A组件</h2>
          <B />
        </div>
      )
    }
  }

  class B extends React.Component {

    constructor (props, context) {
      super(props)

      console.log('B', context.color)
    }

    render () {
      return (
        <div>
          <h2>B组件: {this.context.color}</h2>
          <C />
        </div>
      )
    }
  }

  class C extends React.Component {

    constructor (props, context) {
      super(props)

      console.log('C', context.color)
    }

    /*
    声明接收context中的数据
     */
    static contextTypes = {
      color: PropTypes.string
    }

    render () {
      return (
        <div>
          <h2 style={{color: this.context.color}}>C组件</h2>
        </div>
      )
    }
  }

  ReactDOM.render(<A />, document.getElementById('test'))
</script>

</body>
</html>

上一篇:Dubbo入门2:Springboot+Dubbo2.6.0+ZooKeeper3.4.8整合


下一篇:dubbo基础学习