目录
父子组件之间通信
父组件向子组件传递数据和方法
父组件获取子组件数据和方法
跨级组件之间通信
使用props实现跨级组件通信
使用context实现跨级组件通信
使用状态管理实现跨级组件通信
无关组件之间通信
使用EventEmitter实现无关组件之间通信
使用状态管理实现无关组件通信
补充:自己实现一个EventEmitter
父子组件之间通信
父组件可以向子组件传递数据和方法,子组件通过props来获取。
父组件:
import React from "react";
import Child from "./Child";
export default class Demo extends React.Component {
constructor(props) {
super(props)
this.state = {
value: 0
}
this.changeValue = this.changeValue.bind(this)
}
changeValue() {
this.setState({
value: this.state.value + 1
}, () => {
console.log('changeValue 方法执行了 value: ', this.state.value)
})
}
render() {
const value = this.state.value
return (
父组件
value: {value}
)
}
}
子组件:
import React from "react";
export default class Child extends React.Component {
constructor(props) {
super(props)
}
dealClidk() {
// 子组件触发父组件的方法执行
this.props.changeValue()
}
render() {
return (
子组件
{/* 子组件通过props获取父组件传递的数据 */}
value:{this.props.value}
)
}
}
当点击子组件中的按钮时,就可以通过触发父组件的方法而改变父组件中的属性值。
父组件可以通过ref获取子组件的数据和方法。
父组件:
import React from "react";
import Child from "./Child";
export default class Demo extends React.Component {
constructor(props) {
super(props)
this.ChildRef = React.createRef()
}
dealClidk() {
if (this.ChildRef && this.ChildRef.current) {
// 父组件触发子组件方法的执行
this.ChildRef.current.changeValue()
}
}
getData() {
if (this.ChildRef && this.ChildRef.current) {
// 父组件获取子组件中state的值
const childData = this.ChildRef.current.state.data
console.log('获取子组件的数据 childData: ', childData)
}
}
render() {
return (
父组件
)
}
}
子组件:
import React from "react";
export default class Child extends React.Component {
constructor(props) {
super(props)
this.state = {
data: 0
}
this.changeValue = this.changeValue.bind(this)
}
changeValue() {
this.setState({
data: this.state.data + 1
}, () => {
console.log('changeValue 方法执行了 data: ', this.state.data)
})
}
render() {
const data = this.state.data
return (
子组件
value:{data}
)
}
}
使用props实现跨级组件通信也有两种方法。
直接一级一级的传递
父组件:
import React from "react";
import Child from "./Child";
export default class Demo extends React.Component {
constructor(props) {
super(props)
this.state = {
value: 0,
value2: '张三'
}
this.changeValue = this.changeValue.bind(this)
}
changeValue() {
this.setState({
value: this.state.value + 1
}, () => {
console.log('changeValue 方法执行了 value: ', this.state.value)
})
}
render() {
const { value, value2 } = this.state
return (
父组件
value: {value}
value2: {value2}
)
}
}
子组件:
import React from "react";
import GrandSon from "./GrandSon";
export default class Child extends React.Component {
render() {
const { value, value2 } = this.props
return (
子组件
)
}
}
孙子组件
import React from "react";
export default class GrandSon extends React.Component {
constructor(props) {
super(props)
}
render() {
const { value, value2 } = this.props
return (
孙子组件
value: {value}
value2: {value2}
)
}
}
这种方式适合传递的数据比较少的情况,可以一个一个传递,如果传递的数据比较多的话使用这种方式传递就容易造成代码重复。我们可以使用{...this.props}的方式打包传递。不管父组件传递了多少数据,子组件都打包将所有数据传递给孙子组件,孙子组件依然使用this.props获取即可。
我们修改下子组件的传递方式;
import React from "react";
import GrandSon from "./GrandSon";
export default class Child extends React.Component {
render() {
return (
子组件
)
}
}
可以看到实现了相同的效果。
使用context实现跨级传递数据,需要以下几步:
1、通过React.createContext()创建一个context实例
import React from "react";
const DemoContext = React.createContext()
export default DemoContext;
2、通过provider创建一个生产者,provider有一个value属性可以用来包装所需要传递的数据
import React from "react";
import Child from "./Child";
import DemoContext from './DemoContext'
export default class Demo extends React.Component {
constructor(props) {
super(props)
this.state = {
value: 0,
value2: '张三'
}
this.changeValue = this.changeValue.bind(this)
}
changeValue() {
this.setState({
value: this.state.value + 1
}, () => {
console.log('changeValue 方法执行了 value: ', this.state.value)
})
}
render() {
const { value, value2 } = this.state
return (
父组件
value: {value}
value2: {value2}
)
}
}
3、通过Consumer创建一个消费者,用来接收传递的数据
import React from "react";
import DemoContext from "./DemoContext";
export default class GrandSon extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
孙子组件
{/* Consumer中需要使用函数 */}
{
(value) => {
return (
value: {value.value}
value2: {value.value2}
)
}
}
)
}
}
中间组件:
import React from "react";
import GrandSon from "./GrandSon";
export default class Child extends React.Component {
render() {
return (
子组件
)
}
}
可以参考之前的博客:React-redux全局状态管理
使用EventEmitter的步骤;
1、安装events库
npm install events
2、创建 EventEmitter的实例
import React from "react";
import { EventEmitter } from "events";
// 创建EventEmitter实例
const DemoEvent = new EventEmitter()
export default DemoEvent;
3、发布事件
使用emit("事件名",参数)发布事件
import React from "react";
import DemoEvent from './DemoEvent'
export default class GrandSon extends React.Component {
constructor(props) {
super(props)
this.state = {
value: 0
}
this.changeValue = this.changeValue.bind(this)
}
changeValue() {
this.setState({
value: this.state.value + 1
}, () => {
console.log('changeValue 方法执行了 value: ', this.state.value)
// 发送一个事件
DemoEvent.emit('sendData', this.state.value)
})
}
render() {
return (
孙子组件 GrandSon
{this.state.value}
)
}
}
4、订阅事件
订阅事件可以使用addListener("事件名",回调函数),也可以使用on("事件名",回调函数)
5、取消订阅
取消订阅可以使用removeListener("事件名",回调函数),也可以使用off("事件名",回调函数)
import React from "react";
import DemoEvent from './DemoEvent'
export default class GrandSon2 extends React.Component {
constructor(props) {
super(props)
this.state = {
value: 0
}
this.receiveData = this.receiveData.bind(this)
}
componentDidMount() {
// 订阅事件
DemoEvent.addListener('sendData', this.receiveData)
}
receiveData(data) {
console.log('接收的数据 data: ', data)
this.setState({
value: data
})
}
componentWillUnmount() {
// 取消订阅
DemoEvent.removeListener(this.receiveData)
}
render() {
return (
孙子组件 GrandSon2
{this.state.value}
)
}
}
可以参考之前的博客:React-redux全局状态管理
待续