51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

React 组件之间通信(数据传递)的几种方式

文章已同步至掘金:https://juejin.cn/post/6844903977541173261
欢迎访问😃,有任何问题都可留言评论哦~

在我们使用 React 中,不可避免的要进行组件之间的通信(数据传递)。

需要注意一点:React中数据的流动是单向的

组件之间的数据传递大致分为一下几种:

  • 父组件向子组件传递数据

  • 子组件向父组件传递数据

  • 跨级组件之间传递数据(例如父组件向子子组件传递数据)

  • 非嵌套组件之间传递数据

下面我们使用两种方法 (props和context),分别写段代码来实现上面四种通信的方式

整体通信图解:

react-communication-1

运行效果:

react-communication-2

使用props通信 {#%E4%BD%BF%E7%94%A8props%E9%80%9A%E4%BF%A1}

直接上代码:

import React, { Component } from 'react';

class App extends Component {
state = { color: 'red' }
changeColor = color =\> {
this.setState({ color: color })
}
render() {
return (
\<div style={{ border: `8px solid ${this.state.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Wrapper\</h1\>
\<Header color={this.state.color}\>\</Header\>
\<Main changeColor={this.changeColor.bind(this)} color={this.state.color}\>\</Main\>
\</div\>
)
}
}


class Header extends Component {
render() {
return (
\<div style={{ border: `8px solid ${this.props.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Header\</h1\>
\<Title color={this.props.color}\>\</Title\>
\</div\>
)
}
}


class Title extends Component {
render() {
return (
\<div style={{ border: `8px solid ${this.props.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Title\</h1\>
\</div\>
)
}
}


class Main extends Component {
render() {
return (
\<div style={{ border: `8px solid ${this.props.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Main\</h1\>
\<Content changeColor={this.props.changeColor} color={this.props.color}\>\</Content\>
\</div\>
)
}
}


class Content extends Component {
render() {
return (
\<div style={{ border: `8px solid ${this.props.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Content\</h1\>
\<button onClick={()=\>this.props.changeColor("blue")}\>变蓝\</button\>
\<button onClick={()=\>this.props.changeColor("green")}\>变绿\</button\>
\</div\>
)
}
}

`export default App;
`

图解:

react-communication-3

使用context通信 {#%E4%BD%BF%E7%94%A8context%E9%80%9A%E4%BF%A1}

上面的代码 想必也看到了不足,如果子子组件需要使用父组件的状态,就需要逐级传递在组件中书写传递代码

并且这里面还只是嵌套了两级,组件也比较少,如果组件多,状态多的话怎么办?
套会套会,就把自己给套迷了,所以使用上面方法很容易出现问题,所以在这里我们使用react中给我们提供的api---Context来解决,也就是执行上下文

当然这也不是最优的解决方式,如果是大型项目的话,最好使用Redux来管理我们的状态,如果是小型项目的话,也没必要使用Redux,因为React中自身也提供了状态管理机制

上代码:

import React, { Component } from 'react';

//利用react中提供的api创建一个上下文
let ColorContext = React.createContext();


// Context对象中提供了两个api,一个是 Provider 提供数据
// 另一个是Consumer,  获取数据


// Context.Provder 是一个组件  Context.Provder就表示提供数据的


// static contextType = ColorContext; 加contextType主要就是用来校验的,如果不校验可以不加


class App extends Component {
state = { color: 'red' }
changeColor = color =\> {
this.setState({ color: color })
}
render() {
//获取数据到上下文中
let contextValue = { color: this.state.color, changeColor: this.changeColor }
return (
//使用我们创造的上下文组件把我们写的组件全部包起来,并使用value绑定数据
\<ColorContext.Provider value={contextValue}\>
\<div style={{ border: `8px solid ${this.state.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Wrapper\</h1\>
{/\* 在这里我们就就不需要绑定了 \*/}
\<Header\>\</Header\>
\<Main\>\</Main\>
\</div\>
\</ColorContext.Provider\>
)
}
}


class Header extends Component {
// 然后就需要在子组件中使用这个上下文提供的数据了
// 需要给类加上一个静态属性,值就是这个上下文,哪个组件使用,那就必须加这个话
static contextType = ColorContext;
render() {
return (
// 这里就需要用 this.context 了
\<div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Header\</h1\>
\<Title\>\</Title\>
\</div\>
)
}
}


class Title extends Component {
static contextType = ColorContext;
render() {
return (
\<div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Title\</h1\>
\</div\>
)
}
}


class Main extends Component {
static contextType = ColorContext;
render() {
return (
\<div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Main\</h1\>
\<Content\>\</Content\>
\</div\>
)
}
}


class Content extends Component {
static contextType = ColorContext;
render() {
return (
\<div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Content\</h1\>
\<button onClick={() =\> this.context.changeColor("blue")}\>变蓝\</button\>
\<button onClick={() =\> this.context.changeColor("green")}\>变绿\</button\>
\</div\>
)
}
}

`export default App;
`

图解:

react-communication-4

上面是在类组件中使用上下文,那么如果不是类组件,是函数组件呢?该怎么使用context(上下文)

这里我们把Main的类组件换成函数组件:

import React, { Component } from 'react';
let ColorContext = React.createContext();

class App extends Component {
state = { color: 'red' }
changeColor = color =\> {
this.setState({ color: color })
}
render() {
let contextValue = { color: this.state.color, changeColor: this.changeColor }
return (
\<ColorContext.Provider value={contextValue}\>
\<div style={{ border: `8px solid ${this.state.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Wrapper\</h1\>
\<Header\>\</Header\>
\<Main\>\</Main\>
\</div\>
\</ColorContext.Provider\>
)
}
}


class Header extends Component {
static contextType = ColorContext;
render() {
return (
\<div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Header\</h1\>
\<Title\>\</Title\>
\</div\>
)
}
}


class Title extends Component {
static contextType = ColorContext;
render() {
return (
\<div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Title\</h1\>
\</div\>
)
}
}


// class Main extends Component {
//     static contextType = ColorContext;
//     render() {
//         return (
//             \<div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}\>
//                 \<h1\>Main\</h1\>
//                 \<Content\>\</Content\>
//             \</div\>
//         )
//     }
// }
function Main() {
return (
//需要使用ColorContext.Consumer包起来
\<ColorContext.Consumer\>
{
value =\> (
\<div style={{ border: `8px solid ${value.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Main\</h1\>
\<Content\>\</Content\>
\</div\>
)
}
\</ColorContext.Consumer\>
)
}


class Content extends Component {
static contextType = ColorContext;
render() {
return (
\<div style={{ border: `8px solid ${this.context.color}`, padding: "5px", margin: '5px' }}\>
\<h1\>Content\</h1\>
\<button onClick={() =\> this.context.changeColor("blue")}\>变蓝\</button\>
\<button onClick={() =\> this.context.changeColor("green")}\>变绿\</button\>
\</div\>
)
}
}

`export default App;
`

事实上,在组件间进行通信时,这些通信方式都可以使用,区别只在于使用相应的通信方式的复杂程度和个人喜好,选择最合适的那一个。

当然,自己实现组件间的通信还是太难以管理了,因此出现了很多状态管理工具,如 redux、mobx 等,使用这些工具使得组件间的通信更容易追踪和管理。


TAT {#tat}

赞(2)
未经允许不得转载:工具盒子 » React 组件之间通信(数据传递)的几种方式