React中的context

什么是context

context就是一组属性的集合,并被_隐式_地传递给后代组件。

大家可能会有疑惑,我们不是已经有了props了吗,为什么还需要用context来传递属性呢。可以考虑这么一个情景,有一个层级很深的组件,最里层组件的行为将影响最外层的表现,一般来说我们就会在最外层组件上绑定回调,再一级一级地传入至最内层组件上,通过触发回调来进行上述行为(这里不考虑用flux)。再考虑另外一个情景,在服务端有一个组件需要根据session来渲染,当内部组件需要获取session信息时,就需要从最上层节点一层一层地往下传。但这样的实现不得不说实在有些丑陋,有没有更好的实现方式呢?有,就是使用context。

实例

import ReactDOM from 'react-dom';
import React from 'react'

// Children component
class Children extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.state = {
      name: this.context.name
    };
  }

  render() {
    return(
      <ul>
        <li>
          {`child context is: ${this.context.age}`} // child context is: 18
        </li>
        <li>
          {`state from context: ${this.state.name}`} // state from context: mars
        </li>
        <li>
          {`print age: ${this.context.print(this.context.age)}`} // print age: 18
        </li>
      </ul>
    );
  }
}

Children.contextTypes = {
  name: React.PropTypes.string,
  age: React.PropTypes.number,
  print: React.PropTypes.func
};


// Parent component
class Parent extends React.Component {
  getChildContext() {
    return {
      name: 'mars',
      age: 18
    };
  }

  render() {
    return (
      <div>
        {`from App component: ${this.context.name}`} // from App component: bruno
        <div>
          {this.props.children}
        </div>
      </div>
    );
  }
}

Parent.contextTypes = {
  name: React.PropTypes.string
};
Parent.childContextTypes = {
  age: React.PropTypes.number,
  name: React.PropTypes.string
};

// App component
class App extends React.Component {
  getChildContext() {
    return { 
        name: 'mars',
        print: (m) => m
     };
  }

  render() {
    return (
      <Parent>
        <Children />
      </Parent>
    );
  }
}

App.childContextTypes = {
  name: React.PropTypes.string,
  print: React.PropTypes.func
};

ReactDOM.render(<App />, document.getElementById('app'));

在上面的例子中,我们可以看到在App组价中声明的print方法并没有通过Parent传递,而是通过context直接传递给了Children,这大大方便了我们传值的操作,不再需要一遍一遍地写print={this.props.print}。但同时,我们也需要注意,不要将所有东西都绑定在context上,而是只在必要时使用context,毕竟全局变量很危险。

使用方法

使用getChildContext方法将属性传递给子组件,并使用childContextTypes声明传递数据类型,子组件中需要显式地使用contextTypes声明需要用到的属性的数据类型。

需要传递进context参数才可以在constructor方法中使用context,要不然React将会报错。

在组件中,通过this.context访问context中的属性或方法。

相关api

contextTypes

当需要在当前组件使用从上级组件传入的context的属性时,需要为用到的属性声明数据类型

childContextTypes

声明传递给子组件的属性的数据类型。

getChildContext

设置传递给子组件的属性,可以覆盖,也可以新增。

posted @ 2018-08-23 14:51  我的诗和远方  阅读(501)  评论(0编辑  收藏  举报