React学习之进阶上下文(十九)

来源:互联网 发布:js中offsettop 编辑:程序博客网 时间:2024/06/09 14:37

React中很容易根据组件从而跟踪数据流,当你使用一个组件时,可以通过看props来判断用了哪一些东西。

有时候你想直接通过组件树来讲数据传递子元素,而不是通过props一层一层的传递下去,可以使用React提供的contextAPI来处理。

1.为什么一般都不使用Context

虽然React提供了context来处理以上事件 ,但是一般情况下是不需要使用这个API的。

如果你想要你的应用尽可能的稳定的话,请不要使用Context,因为这在React属于一种实验性质的API,在未来的React版本中可能被抛弃。

如果你不是一个非常有经验的开发人员,也请不要使用context,通常都有更好方法来实现我们的要求

如果你硬是要用Context,请在小范围中使用

2.使用context的方法

class Button extends React.Component {  render() {    return (      <button style={{background: this.props.color}}>        {this.props.children}      </button>    );  }}class Message extends React.Component {  render() {    return (      <div>        {this.props.text} <Button color={this.props.color}>Delete</Button>      </div>    );  }}class MessageList extends React.Component {  render() {    const color = "purple";    const children = this.props.messages.map((message) =>      <Message text={message.text} color={color} key={index} />    );    return <div>{children}</div>;  }}

上面的我们给button设置颜色,竟然要从顶层的组件一步一步的通过props传递下去,很烦。

如果是使用context就会非常简单了

class Button extends React.Component {  render() {    return (      <button style={{background: this.context.color}}>        {this.props.children}      </button>    );  }}//重点Button.contextTypes = {  color: React.PropTypes.string};class Message extends React.Component {  render() {    return (      <div>        {this.props.text} <Button>Delete</Button>      </div>    );  }}class MessageList extends React.Component {//重点  getChildContext() {    return {color: "purple"};  }  render() {    const children = this.props.messages.map((message, index) =>      <Message text={message.text} key={index}/>    );    return <div>{children}</div>;  }}//重点MessageList.childContextTypes = {  color: React.PropTypes.string};

通过childContextTypesgetChildContextMessageList增加context上下文,React会自动将它传递给子组件,如果子组件设置了contextTypes就会获取到这个上下文。如果子组件的contextTypes没有设置的话,context就会是一个空的。

3.父子耦合

context可以让父组件和子组件建立一个直接数据交流的通道,React Router V4就实现了这个功能,这里不详讲。

4.在生命周期函数中使用context

需要将context通过参数传递

constructor(props, context)componentWillReceiveProps(nextProps, nextContext)shouldComponentUpdate(nextProps, nextState, nextContext)componentWillUpdate(nextProps, nextState, nextContext)componentDidUpdate(prevProps, prevState, prevContext)

上面这些函数以后会讲解

5.无状态函数式组件中的context

这里先声明一下函数式组件本身无法使用this.state来进行状态标记控制

const Button = ({children}, context) =>  <button style={{background: context.color}}>    {children}  </button>;Button.contextTypes = {color: React.PropTypes.string};

当我们将context当做参数传入函数式组件,并且contextTypes进行了类型检测控制,就可以在函数式组件内部使用context

6.更新Context

虽然React有更新Context的函数,但是对不起,依旧不希望你去使用context,这算是警告中的警告了。

在前面写的时候,我就已经使用getChildContext来处理数据,这个函数会在stateprops改变时被调用。只要对stateprops进行更新就可以实现context的更新。

class MediaQuery extends React.Component {  constructor(props) {    super(props);    this.state = {type:'desktop'};  }  getChildContext() {    return {type: this.state.type};  }  componentDidMount() {    const checkMediaQuery = () => {      const type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';//这个是用来识别是PC端还是移动端(IE10+)      if (type !== this.state.type) {        this.setState({type});      }    };    window.addEventListener('resize', checkMediaQuery);    checkMediaQuery();  }  render() {    return this.props.children;  }}MediaQuery.childContextTypes = {  type: React.PropTypes.string};

当然使用这个更新也会出问题,就是我们的shouldComponentUpdate函数返回false的时候,会导致子组件不更新状态,从而让子组件的context超出控制。

下一篇将讲React中的WEB组件

1 0