1.父组件与子组件通信
父组件将自己的状态传递给子组件,子组件当做属性来接收,当父组件更改自己状态的时候,子组件接收到的属性就会发生改变
App.js
import React, { Component } from 'react'
import Grandfather from './father-to-son/Father'
export default class App extends Component {
render() {
return (
<div>
<Father/>
</div>
)
}
}
father-to-son/Father.js
import React, { Component } from 'react'
import Son from './Son'
export default class Father extends Component {
state={
money:2000
}
render() {
const {money}=this.state
return (
<div>
<Son money={money}/>
</div>
)
}
}
father-to-son/Son.js
//类组件
// import React, { Component } from 'react'
// export default class Son extends Component {
// render() {
// const {money}=this.props//通过属性解构
// return (
// <div>
// <p>老爸给了我{money}</p>
// </div>
// )
// }
// }
//函数组件
import React from 'react'
export default function Son(props) {
const {money}=props
return (
<div>
<p>老爸给了我{money}</p>
</div>
)
}
2. 子组件与父组件通信
父组件传递个方法给子组件,子组件触发这个方法并传参
son-to-father/Father.js
import React, { Component } from 'react'
import Son from './Son'
//父组件传递个方法给子组件,子组件触发这个方法并传参
export default class Father extends Component {
state={
jinku:800
}
addJK=hongbao=>{
this.setState({
jinku:this.state.jinku+hongbao
})
}
render() {
const {jinku}=this.state
return (
<div>
<p>老爸有{jinku}</p>
<Son addJK={this.addJK}/>
</div>
)
}
}
son-to-father/Son.js
import React, { Component } from 'react'
export default class Son extends Component {
state={
money:2000
}
render() {
const {money}=this.state
const {addJK}=this.props
return (
<div>
<button onClick={()=>{addJK(money)}}>给老爸发红包</button>
</div>
)
}
}
3. 非父子组件通信
brother/Father.js
import React, { Component } from 'react'
import Sister from './Sister'
import Son from './Son'
//非父子组件通信,需要借助一个共有的父组件来操作
export default class Father extends Component {
hick=()=>{
// console.log('this',this)
// this.refs.son.changeFlag()
this.son.changeFlag()//相比上面的获取方法,这样写减少了层级嵌套
}
render() {
return (
<div>
<Sister hick={this.hick}/>
{/* 这里的son指代的就是Son组件 */}
{/* <Son ref="son"/> */}
{/* el指的就是Son组件,将Son组件作为属性值赋值给了Father组件的son属性 */}
<Son ref={el=>this.son=el}/>
</div>
)
}
}
brother/Son.js
import React, { Component } from 'react'
export default class Son extends Component {
//定义一个状态来控制vdom的显示和隐藏
state={
flag:true
}
//组件自己的状态自己控制
changeFlag=()=>{
this.setState({
flag:!this.state.flag
})
}
render() {
const {flag}=this.state
return (
<div>
{flag && <p>笑</p> || <p>哭</p>}
</div>
)
}
}
brother/Sister.js
import React, { Component } from 'react'
export default class Sister extends Component {
render() {
return (
<div>
{/* 姐姐需要拿到Son组件上的changeFlag方法,用过Father组件 */}
<button onClick={this.props.hick}>打弟弟</button>
</div>
)
}
}
4. 跨组件通信
在react没有类似vue中的事件总线来解决这个问题,我们只能借助它们共同的父级组件来实现,将非父子关系装换成多维度的父子关系。react提供了context api来实现跨组件通信, React 16.3之后的contextapi较之前的好用。
stride-component/Grandfather.js
import React, { Component } from 'react'
import Father from './Father'
import {moneyContext} from '../context'
export default class Grandfather extends Component {
state={
money:2000
}
render() {
const {money}=this.state
return (
<div>
<moneyContext.Provider value={money}>
<Father/>
</moneyContext.Provider>
</div>
)
}
}
stride-component/Father.js
import React, { Component } from 'react'
import Son from './Son'
export default class Father extends Component {
render() {
return (
<div>
<Son/>
</div>
)
}
}
stride-component/Son.js
import React, { Component } from 'react'
import {moneyContext} from '../context'
export default class Son extends Component {
static contextType=moneyContext
render() {
return (
<div>
<p>爷爷给了我{this.context}</p>
</div>
)
}
}
context/index.js
//context 上下文,也叫投影
import {createContext} from 'react'
export const moneyContext=createContext(0)//设置一个初始值