一、组件间通信
组件间通信我们主要讲述下面几种情况:
-
父组件给子组件传递
-
子组件给父组件传递
-
同级组件传递
-
跨组件通信
父传子
只需要在父组件调用子组件的时候,将传递的信息加载子组件的属性中,子组件通过props接收父组件传递过来的值
父组件
function Father() {
const data = { foo: "foo" }
return (
<Children data={data}></Children>
)
}
子组件
function Children(props){
const { data } = props // 接收父组件传递过来data的值
}
子传父
由于react中数据传递是单向的,数据流只能从父组件流向子组件
如果子要传递数据给父组件,可以首先在父组件中定义一个接收数据的回调函数,再将这个回调函数传递给子组件
父组件
class Father extends Component {
state = {
openKey : "friend" //应该展开项的 key 值,为空则都不展开
}
openMenu = (name)=>{ // 1.定义一个接收子组件传递数据的函数
this.setState({
openKey: name
});
}
render() {
const {openKey} = this.state;
return <div className="friend-list">
<Children
openMenu={openKey} // 2.将函数传递给组件
></Children>
</div>
}
}
子组件
function Children(props){
const { openMenu } = this.props
return (
<button onClick={()=>{openMenu('子组件的值')}} // 3.子组件将值传递给父组件
)
}
同级组件传递
子组件间数据传递可以通过先将数据传给他们共同的父组件,再由父组件传给子组件
当一个子组件1想要给另一个子组件2传递数据,我们可以分解成以下几个步骤:
- 父组件定义回调函数,将回调函数传递给子组件1,将值传递给子组件2
- 子组件1接收父组件的回调函数,通过调用回调函数传递数据给父组件
- 子组件2接收父组件传递过来的值,也就是子组件1传递给父组件2的值
代码演示下:
实例代码:
父组件定义回调函数,将回调函数传递给子组件1,将值传递给子组件2
class Father extends Component {
state = {
foo: "foo"
}
change = (value) => {
this.setState({
foo:value
})
}
render() {
return (
<>
<Children1 change={this.change}></Children1> // 传递回调函数
<Children2 data={this.state.foo}></Children2> // 传递值
</>
)
}
}
子组件1接收父组件的回调函数,通过调用回调函数传递数据给父组件
function Children1(props) {
const { change } = props
return (
<button onClick={() => {
change('子组件1的值')
}}>子组件1</button>
)
}
子组件2接收父组件传递过来的值,也就是子组件1传递给父组件2的值
function Children2(props) {
const { data } = props // 接收同级组件传递过来的值
return (
<p>{data}</p>
)
}
跨组件
这里讲述React.createContext(defaultValue)
实现流程如下:
导入createContext
import {createContext} from "react";
创建上下文
const context = createContext();
在context上下文中,存在Provider、Consumer组件
const {Provider,Consumer} = context;
Provider顾名思义,用来提供数据的
Consumer顾明思议,用来消费数据的,也就是得到数据
只需要在父组件中,通过Provider包裹组件,那么里面的组件都能得到该父组件传递过来的值
class App extends Component {
state = {
count: 1
}
add = () => {
const { count } = this.state;
this.setState({
count:count + 1
});
}
render() {
const { count } = this.state;
return <Provider
value={{
count:count,
add:this.add
}}
>
<Child />
</Provider>
}
}
在Provider的组件,可以通过Consumer组件包裹得到数据
class SubChild extends Component {
render() {
console.log(this);
return <>
<Consumer>
{(context)=>{ // Provide传递过来的value
console.log(context);
return <div></div>
}}
</Consumer>
</>
}
}
也可以通过contextType得到Provide数据
class SubChild extends Component {
static contextType = context;
render() {
//console.log(this);
const {count,add} = this.context; // 得到Procider传递过来的值
return <>
<p>count:{count}</p>
<button onClick={()=>{
add();
}}>递增</button>
</>
}
}
关于Consumer和contextType的区别:
Consumer书写起来不雅观,但是可以写多个Consumer得到各个Provider传递过来的值contextType只能接收一个Provider传递过来的值