React间组件间通信有如下几种方式:
- 父组件向子组件通信
- 子组件向父组件通信
- 跨级组件通信
- 非嵌套关系的组件通信
父组件向子组件通信
父组件直接通过props向子组件传递需要的信息
// 子组件
const Child = props => {
return <p>{props.name}</p>
}
// 父组件
const Parent = ()=>{
return <Child name='哈哈哈'/>
}
子组件向父组件通信
props+回调。即父组件通过props传递方法下去,子组件调用这个方法。
// 子组件
const Child = props=> {
const test = msg=> {
return () => {
props.callback(msg);
}
}
return (
<Button onClick={test('子组件的数据')}>按钮</Button>
)
}
// 父组件
class parent extends Component{
callback = (msg) => {
console.log('子组件的数据:' + msg);
}
render(){
return <Child callback={this.callback}>
}
}
跨级组件通信
- 使用props进行多级传递,但是增加了复杂度
- 使用context,context相当于一个大容器,不管多少层都可以轻松拿到,对于跨越多层的数据可以采用这个方案。
官网Context详细介绍https://react.docschina.org/docs/context.html
// Context 可以让我们无须明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
class App extends React.Component {
render() {
// 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
// 无论多深,任何组件都能读取这个值。
// 在这个例子中,我们将 “dark” 作为当前的值传递下去。
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
}
// 中间的组件再也不必指明往下传递 theme 了。
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
class ThemedButton extends React.Component {
// 指定 contextType 读取当前的 theme context。
// React 会往上找到最近的 theme Provider,然后使用它的值。
// 在这个例子中,当前的 theme 值为 “dark”。
static contextType = ThemeContext;
render() {
return <Button theme={this.context} />;
}
}
非嵌套关系的组件通信
- 使用redux等状态管理工具
- 可以使用自定义事件通信(发布订阅模式)
设置一个event文件
class Event{
constructor() {
this.eventList = [];
}
// 绑定事件
$on = (eventName, cb)=> {
// 判断该类型的事件是否存在,若存在则添加
let lists = this.eventList[eventName];
if(!lists){
this.eventList[eventName] = []
}
this.eventList[eventName].push(cb)
}
// 触发事件
$emit = (eventName, params) => {
// 先判断事件类型是否存在
let lists = this.eventList[eventName];
if(!lists) {
throw new Error('无此事件类型')
}
// 若存在则执行
lists.forEach((item)=>{
item(params);
});
}
$off = (eventName, cb) => {
let lists = this.eventList[eventName];
if(lists){
// 若第二个参数存在,则删除该类型下指定的方法,若不存在则删除整个类型
if(!cb){
this.eventList[eventName] = []
}else{
this.eventList[eventName] = lists.filter((item)=>{
return item !=cb;
})
}
}
}
}
使用示例
a文件里触发
import Event from 'event'
class A extends React.Component {
componentDidMount() {
Event.on('data1Change', this.handleData1Change)
}
handleData1Change = ()=>{
console.log('测试')
}
}
b文件里触发
import Event from 'event'
class B extends React.Component {
handleUpdateData = () => {
Event.emit('data1Change')
}
}
最新回复