一、Context 的认识
- 在
React
中,父子组件通信的机制,父子组件的通信是通过props
进行数据的传递,如下所示:
- 父组件向子组件传递数据(状态)时,是在调用子组件的时候通过参数传递给子组件,子组件通过
this.props
进行接收 - 子组件如果更改父组件的一些属性,则是通过父组件定义的方法来传递给子组件,子组件调用更改
- 如果父组件想要更改子组件的一些状态时,通过
ref
进行标记,可以获取子组件的所有信息,从而调用子组件的方法和值 - 当层级很多时,使用
props
进行逐层的传递,是不行的,而context
就可以解决
-
context
通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递props
属性。如果我们不想通过props
实现组件树的逐层传递数据,则可以使用context
实现跨层级进行数据传递。 -
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>
-
每当
Provider
的值发生改变时, 作为Provider
后代的所有Consumers
都会重新渲染。props
是单向数据流动,所以当props
传递数据很繁琐,可以采用context
,进行跨组件传递数据。在最外层的组件上,通过生产者Provider
组件进行包裹,并存储共享数据到value
中,当然可以是任何数据类型。后带需要用到共享数据的组件均可通过Consumer
进行数据获取。 -
对于
React
中context
的简单应用,代码如下所示:
<!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>