本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
不管是Vue或者是React,组件通讯都是必备的,本文主要介绍React组件之间通讯方式。
1.父子之间的通讯
1.1 父传子
父组件通过
props
传参给子组件
// 父组件
import { useState } from 'react';
import Child from './child'
export default function HelloWorld() {
const [name, setName] = useState('豆豆')
return (
<div>
// 把name传递给子组件
<Child name={name} />
</div>
)
}
// 子组件
import { useState } from 'react';
// 子组件利用对象解构赋值接收父组件传递的 name
export default function Child({name}) {
return (
<div>
// 子组件展示父组件传递的 name 值
{ name }
</div>
)
}
1.2 子传父
父组件传递
changeName
方法给子组件,让子组件执行该方法,通过函数传参的方式来完成子组件给父组件参传
// 父组件
import { useState } from 'react';
import Child from './child'
export default function HelloWorld() {
const [name, setName] = useState('豆豆')
// val的值通过子组件传递过来
const changeName = val => {
setName(val)
}
return (
<div>
{name}
// 把 changeName 传递给子组件
<Child changeName={changeName} />
</div>
)
}
// 子组件
import { useState } from 'react';
// 子组件接收 changeName 方法
export default function Child({changeName}) {
const handleClick = () => {
// 执行父组件传递过来的方式,并且给父组件传值
changeName('一只豆豆')
}
return (
<div>
<button onClick={handleClick}>click my</button>
</div>
)
}
2.跨组件的通讯
2.1 先创建一个 MyContext.js
利用
React.createContext
创建一个MyContext,并且可以设置默认值
import React from 'react'
export const MyContext = React.createContext(
// 在这里可以设置默认值
{ name: '豆豆' },
)
2.2 在祖先组件引入 MyContext.js
用
MyContext.Provider
包裹父组件 通过value={xxx}
传值
import { useState, } from 'react';
import Child from './child'
import { MyContext } from './context'
export default function HelloWorld() {
const [name, setName] = useState('一只豆豆')
return (
<div>
// 包裹组件并且传递 name
<MyContext.Provider value={name}>
<Child />
</MyContext.Provider>
</div>
)
}
2.3 子组件引入孙子组件
只需要引入son组件 使用即可,不需要任何操作了
import { useState } from 'react';
import Son from './son'
export default function Child() {
return (
<div>
<Son />
</div>
)
}
2.4 孙子组件使用传递过来的数据
用
MyContext.Consumer
包裹一个函数式组件,该函数式组件的参数,可以接收该组件的上级组件中最近一个被MyContext.Provider
包裹的组件中传递给MyContext.Provider
的属性value
的数据。
import { useState } from 'react';
import { MyContext } from './context'
export default function Son() {
return (
<div>
<MyContext.Consumer>
{ value => (<div>{ value }</div>) }
</MyContext.Consumer>
</div>
)
}
3.EventBus通讯
Vue2有
EventBus
的API,通过$on
和$emit
来进行通讯, React没有EventBus
API,我们可以利用node.js提供的events.js来实现
npm install events --save
先下载events.js
3.1 先创建一个 bus.js 文件
import { EventEmitter } from 'events'
const eventBus = new EventEmitter()
export default eventBus
3.2 兄弟组件Aemit
发送事件
import bus from './bus'
export default function A() {
const handleClick = () => {
bus.emit('click', '爱在西元前')
}
return (
<>
<button onClick={handleClick}>click my</button>
</>
)
}
3.3 兄弟组件Bon
监听事件
import { useEffect } from 'react';
import bus from './bus'
export default function B() {
bus.on('click', val => {
console.log('val', val); // 爱在西元前
})
return (
<>
<div>
兄弟组件B
</div>
</>
)
}
3.4 兄弟组件Boff
销毁事件
import { useEffect } from 'react';
import bus from './bus'
export default function B() {
const handleClick = val => {
console.log('val', val); // 爱在西元前
}
useEffect(() => {
// 监听事件
bus.on('click', handleClick)
return () => {
// 销毁事件
bus.off('click', handleClick)
}
}, [])
return (
<>
<div>
test
</div>
</>
)
}
4.父组件调用子组件方法
在Vue中可以通过
ref
去调用子组件的方式;
在React中可以通过useImperativeHandle
把子组件的方法暴露出去;
// 父组件
import React, { useRef } from "react"
import Child from './child'
export default function Father() {
const myRef = useRef()
const handleClick = () => {
// 点击按钮时执行子组件的handleClick方法
myRef.current.handleClick()
}
return (
<>
<div>
父组件
<button onClick={handleClick}>click my</button>
<Child ref={myRef} />
</div>
</>
)
}
// 子组件
import React, { useImperativeHandle, forwardRef } from "react"
const Child = (props, ref) => {
useImperativeHandle(ref, () => ({
handleClick: () => {
console.log('七里香');
}
}))
return (
<>
<div>
子组件
</div>
</>
)
}
export default forwardRef(Child) // useImperativeHandle配合forwardRef一起使用
结语
有帮助的话,给个赞哈。如果有错误欢迎在评论区指出。