React里面的api:
React.createContext (通过这个api完成跨级传值)里面有如下:
Provider 外层 生产数据 (数据的生产者)
Consumer 内层 消费数据 (数据的消费者)
这两个都是组件
作用:方便祖先组件与后代组件传值
也就是通过React.createContext()创建一个Context对象,这个Context对象包含两个组件< Provider />和< Consumer />
示例代码
views里面新建:
Home.js父组件
Son.js子组件和Grandson.js孙子辈组件
它们是互相嵌套的关系
Home里包含Son子组件
Son组件包含Grandson组件
Home.js:
import React, { Component } from 'react'
import Son from './Son'
export default class Home extends Component {
render() {
return (
<div>
<Son/>
</div>
)
}
}
Son.js:
import React, { Component } from 'react'
import Grandson from './Grandson'
export default class Son extends Component {
render() {
return (
<div>
Son
<Grandson/>
</div>
)
}
}
Grandson.js:
import React, { Component } from 'react'
export default class Grandson extends Component {
render() {
return (
<div>
Grandson
</div>
)
}
}
先打开页面查看是否能正常显示内容:
然后在src文件夹下创建utils文件夹,里面新建GrandParentContext.js文件
现在的情况是,我们有一个父组件Home,在这个父组件里有一个Son儿子组件。
而在Son儿子组件中,又包含了Grandson孙子组件。
那么如果我们想将父组件的值,传递给孙子组件的话,就是跨组件传值,就要用到createContext这个方法了。
回到Home.js里:
将创建的GrandParentContext引入 并模拟一个想要传到孙子组件的数据
import React, { Component } from 'react'
import Son from './Son'
import GrandParentContext from '../utils/GrandParentContext'
export default class Home extends Component {
state = {
obj: {
name: '这是一个名字',
age: 12
}
}
render() {
return (
//要使用Provider将子组件包裹起来 值传到子组件,必须使用value
<GrandParentContext.Provider value={this.state.obj}>
<div>
<Son />
</div>
</GrandParentContext.Provider>
)
}
}
Provider有一个固定的value属性,传递给消费组件。当value值发生变化时,它内部的所有消费组件都会重新渲染
最后到Grandson组件:
打开页面查看:
上面这个使用static是向上级找组件,用它就不用再使用Consumer这个组件了
如果想使用这个组件,可以这么写:
import React, { Component } from 'react'
import GrandParentContext from '../utils/GrandParentContext'
export default class Grandson extends Component {
//想上级找Provider
//static contextType = GrandParentContext
render() {
return (
<div>
Grandson
{/* <h3>姓名:{this.context.name}</h3>
<h3>年龄{this.context.age}</h3> */}
<GrandParentContext.Consumer>
{
(store) => {
return <div>
<h3>姓名:{store.name}</h3>
<h3>姓名:{store.age}</h3>
</div>
}
}
</GrandParentContext.Consumer>
</div>
)
}
}
总结
- 单独的文件中创建一个Context对象
- 使用Provider进行传值(用于上层组件)
- 内层组件接收值(this.context)
内层组件向外层组件传值(子传父)
比如在Grandson这个里层组件里有个button,当点击时,会传一个值给外层组件Home
首先在最外层Home.js里:定义一个回调
然后到Son.js里:只需要将从父组件传过来的方法再传给它的子组件Grandson
import React, { Component } from 'react'
import Grandson from './Grandson'
export default class Son extends Component {
render() {
return (
<div>
Son
<Grandson btnClick={this.props.btnClick}/>
</div>
)
}
}
接着到Grandson.js里:将传过来的方法执行
import React, { Component } from 'react'
import GrandParentContext from '../utils/GrandParentContext'
export default class Grandson extends Component {
//想上级找Provider
static contextType = GrandParentContext
render() {
return (
<div>
Grandson
<h3>姓名:{this.context.name}</h3>
<h3>年龄{this.context.age}</h3>
<button onClick={()=>{
this.props.btnClick('我是Grandson组件传过去的值')
}}>点击传递到外层组件</button>
{/* <GrandParentContext.Consumer>
{
(store) => {
return <div>
<h3>姓名:{store.name}</h3>
<h3>姓名:{store.age}</h3>
</div>
}
}
</GrandParentContext.Consumer> */}
</div>
)
}
}
这也就是相当于,把值先传到Son里面,再传到Home里
打开页面点击按钮查看:
注意:
外层组件的createContext()必须和内层组件的createContext是同一个对象