引言
在我们React组件开发中,当一个父组件的想要往自己的子孙组件传值的时候,可以使用 props
属性,但是其每一个子组件,都要向下传递数据,这样造成的数据的耦合性,所以在 React 官方文档中 提供了 context
特性来解决,这个问题。
父子组件之间的通信
我们先看一下React中,父子组件通信的机制,父子组件的通信是通过props进行数据的传递:
- 父组件向子组件传递数据(状态)时,是在调用子组件的时候通过参数传递给子组件,子组件通过this.props进行接收;
- 子组件如果更改父组件的一些属性,则是通过父组件定义的方法来传递给子组件,子组件调用更改;
- 如果父组件想要更改子组件的一些状态时,通过ref进行标记,可以获取子组件的所有信息,从而调用子组件的方法和值;
但是,如果层级很多呢,是否需要多个props进行逐层的传递?答案是否定的,React的advanced(高级)中指出了context,优雅的解决这个问题。
好的,接下来我们来介绍一下这个特性Context
我们知道,在JS中context指的是函数的执行上下文,函数被调用时,this指向谁,谁就是当前的执行上下文;
- react中的context是什么呢?官方文档给出:
- Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。
文档也没具体给出context到底是什么,而是告诉我们context能干什么,也就是说,如果我们不想通过props实现组件树的逐层传递数据,则可以使用context实现跨层级进行数据传递!
如何使用 Context 呢?
context api给出三个概念:React.createContext()、Provider、Consumer;
- React.createContext()
这个方法用来创建context对象,并包含Provider、Consumer两个组件 <Provider />、<Consumer /> const {Provider, Consumer} = React.createContext();
- Provider
数据的生产者,通过value属性接收存储的公共状态,来传递给子组件或后代组件 eg: <Provider value={/* some value */}>
- Consumer
数据的消费者,通过订阅Provider传入的context的值,来实时更新当前组件的状态 eg: <Consumer> {value => /* render something based on the context value */} </Consumer>
值得一提的是每当Provider的值发生改变时, 作为Provider后代的所有Consumers都会重新渲染
props单向数据流动:

如果觉得Props传递数据很繁琐,可以采用context,进行跨组件传递数据

再最外层的组件上,通过生产者Provider组件进行包裹,并存储共享数据到value中,当然可以是任何数据类型。后带需要用到共享数据的组件均可通过Consumer进行数据获取
代码演示
import React from 'react' import ReactDOM from 'react-dom' // 创建一个 textcont 特性的 const {Provider,Consumer} = React.createContext('顶顶顶') class Person extends React.Component{ constructor(props){ super(props) this.state = { color : 'red' } } render(){ return ( <Provider value={this.state.color}> <h1>我是父组件</h1> <Son></Son> </Provider> ); } } class Son extends Person{ render(){ return <div> <h3>我是子组件</h3> <Son1></Son1> </div> } } class Son1 extends Son{ render(){ return ( <Consumer> { (color) => <div> <h6 style={{color}}>我是孙子组件-----{color}</h6> </div> } </Consumer> ); } } ReactDOM.render(<div> <Person></Person> </div>,document.getElementById('app'))
参考作品出处:
https://segmentfault.com/a/1190000017758300
来源:https://www.cnblogs.com/ifon/p/11514307.html