组件通信的目的 : 传递或共享某些数据;
常见组件通信方式:父传子、子传父、兄弟相传、跨组件通信等。
父传子
步骤
-
父组件(使用组件的地方)通过自定义属性提供数据。
-
子组件(定义组件的地方)通过 this.props/props 接收。
类组件:通过 this.props
接收。
// 父组件
import React, { Component } from 'react'
import Child from './Child'
class Parent extends Component {
state = {
salary: 11.46,
}
render() {
return (
<div style={{ border: '1px solid gray', padding: 20, width: 300 }}>
<h3>工资</h3>
<Child salary={this.state.salary}></Child>
</div>
)
}
}
export default Parent
// 子组件
import React, { Component } from 'react'
export default class Child extends Component {
render() {
return <div style={{ border: '1px solid red' }}>子:{this.props.salary}</div>
}
}
函数组件:通过 props
接收。===> 函数组件没有this
const Child = (props) => {
return <div style={{ border: '1px solid red' }}>子:{props.salary}</div>
}
export default Child
注意事项:
Props 是只读的,不能修改。
-
父组件中的数据更新时,子组件接收到的数据也会自动更新。子组件不能直接修改父组件的数据;
-
传递的数据可以是任意类型:数字、字符串、布尔、对象、函数、JSX 等。
-
使用类组件时,如果写了构造函数,应该在 constructor 中接收 props,并将 props 传递给 super,否则无法在构造函数中使用 this.props。
子传父
步骤:
1,父组件通过属性传递一个回调函数。
2,子组件调用传递过来的回调函数,并将要传递的数据作为回调函数的实参。
3,父组件在回调函数中通过形参接收传递过来的数据并做相应操作。
// 父组件
import React from 'react'
import Hello from './Hello'
export default class App extends React.Component {
// 注意这个函数要是箭头函数,保证 this 指向自己的组件实例
getChildMsg = (msg) => {
// #3 在回调函数中接收参数
console.log('接收到的子组件的数据:' + msg)
}
render() {
return (
<div>
父组件
<hr />
{/* #1 父组件提供回调函数 */}
<Hello getMsg={this.getChildMsg} />
</div>
)
}
}
// 子组件
class Hello extends React.Component {
state = {
childMsg: 'Hello',
}
handleClick = () => {
// #2 子组件调用传递过来的回调函数并传参
this.props.getMsg(this.state.childMsg)
}
render() {
return (
<div>
<button onClick={this.handleClick}>点我,向父组件传递数据</button>
</div>
)
}
}
兄弟通信
步骤
-
准备 A、B 兄弟组件。
-
把需要操作的 B 组件中的数据 count 提升到公共的父组件里面。
-
父组件提供数据和操作数据的方法。
-
把数据传递给 B 组件,把操作数据的方法传递给 A 组件。
// 父组件
import React, { Component } from 'react'
import A from './A'
import B from './B'
export default class App extends Component {
state = {
count: 0,
}
changeCount = (num) => {
this.setState({
count: this.state.count + num,
})
}
render() {
return (
<div>
<A changeCount={this.changeCount} />
<hr />
<B count={this.state.count} />
</div>
)
}
}
// 子组件A
import React, { Component } from 'react'
export default class A extends Component {
render() {
return (
<div>
A<button onClick={() => this.props.changeCount(3)}>+1</button>
</div>
)
}
}
// 子组件B
import React, { Component } from 'react'
export default class B extends Component {
render() {
return <div>B:{this.props.count}</div>
}
}
跨级组件通讯
步骤:
-
祖先组件通过
React.crateContext()
创建 Context 并导出。 -
祖先组件通过
<Context.Provider>
配合 value 属性提供数据。 -
后代组件通过
<Context.Consumer>
配合函数获取数据。 -
优化:提取
React.crateContext()
到单独的文件里面。
创建App.js,A.js,B.js三个文件 App中引入A ,A中引入B
// App
import React, { Component, createContext } from 'react'
import A from './A'
export const context = createContext()
export default class App extends Component {
state = {
money: 8888,
}
changeMoney = (n) => {
this.setState({
money: this.state.money + n,
})
}
render() {
return (
<context.Provider
value={{
money: this.state.money,
changeMoney: this.changeMoney,
}}
>
App
<hr />
<A />
</context.Provider>
)
}
}
// A组件
import React, { Component } from 'react'
import B from './B'
export default class A extends Component {
render() {
return (
<div>
A
<hr />
<B />
</div>
)
}
}
// B组件
import React, { Component } from 'react'
import { context } from './App'
export default class B extends Component {
render() {
return (
<context.Consumer>
{(value) => {
return (
<div>
<h1>{value.money}</h1>
<button onClick={() => value.changeMoney(8)}>changeMoney</button>
</div>
)
}}
</context.Consumer>
)
}
}