组件通信的意义
组件时独立且封闭的单元,默认情况下组件只能使用自己的数据(state)组件开发的过程中,完整的功能会拆分多个组件,在这个过程中不可避免的需要互相传递一些数据,为了能够让各组件之间可以互相沟通,数据传递,这个过程就是组件通信。
1.父子关系 - 最重要
2.兄弟关系 - 自定义事件模式产生技术方法eventBus/ 通过共同的父组件通信
3.其他关系 - mobx / redux / 基于hook的方案
父传子实现:
import React from 'react'
// APP 父组件 Son子组件
// 函数式子组件
function SonF (props) {
// props 是一个对象,里边包含了父组件传入的所有数据
return (
<div>我是函数式子组件:{props.msg}</div>
)
}
// 类子组件
class SonC extends React.Component {
render () {
return (
<div>我是类子组件:{this.props.msg}</div >
)
}
}
// 提供数据的父组件
class App extends React.Component {
// 准备数据
state = {
message: 'This is message'
}
render () {
return (
<div className="app">
{/* 子组件身上绑定属性,属性名可以自定义 */}
<SonF msg={this.state.message} />
<SonC msg={this.state.message} />
</div >
)
}
}
export default App
import React from 'react'
// APP 父组件 Son子组件
// 函数式子组件
function SonF (props) {
console.log(props)
// props 是一个对象,里边包含了父组件传入的所有数据
return (
<div>我是函数式子组件:
{props.list.map(item => <p key={item}>{item}</p>)}
<ul>
<li>姓名:{props.userInfo.name}</li>
<li>年龄:{props.userInfo.age}</li>
<button onClick={props.getMes}>函数</button>
</ul>
{props.child}
</div>
)
}
function SonF2 (props) {
console.log(props)
// 结构赋值
const { list, userInfo, getMes, child } = props
// props 是一个对象,里边包含了父组件传入的所有数据
return (
<div>我是函数式子组件:
{list.map(item => <p key={item}>{item}</p>)}
<ul>
<li>姓名:{userInfo.name}</li>
<li>年龄:{userInfo.age}</li>
<button onClick={getMes}>函数</button>
</ul>
{child}
</div>
)
}
// 提供数据的父组件
class App extends React.Component {
// 准备数据 传递数据的类型:string 数组 对象 函数 jsx
state = {
message: 'This is message',
list: [1, 2, 3],
userInfo: {
name: 'jxe',
age: 24,
}
}
getMes = () => {
console.log("父组件函数")
}
render () {
return (
<div className="app">
{/* 子组件身上绑定属性,属性名可以自定义 */}
<SonF
list={this.state.list}
userInfo={this.state.userInfo}
getMes={this.getMes}
child={<span>this is span</span>} />
<SonF2
list={this.state.list}
userInfo={this.state.userInfo}
getMes={this.getMes}
child={<span>this is span</span>} />
</div >
)
}
}
export default App
子传父本质:
import React from 'react'
// APP父组件 Son子组件
// 父传子 props 函数
// 子传父 子组件调用父组件传递过来的函数,并且把想要传递的数据当成函数的实参,传入即可
function SonF (props) {
const { getSonMes } = props
const msg = '这是子组件的数据'
function clickHandle () {
getSonMes(msg)
}
return (
<div>this is son <button onClick={clickHandle}>按钮</button></div>
)
}
class App extends React.Component {
state = {
message: 'This is message',
list: [1, 2, 3],
}
getSonMes = (sonMsg) => {
console.log(sonMsg)
}
render () {
return (
<div className="app">
{/* 子组件身上绑定属性,属性名可以自定义 */}
<SonF getSonMes={this.getSonMes} />
</div >
)
}
}
export default App
兄弟组件通信实现:
import React from 'react'
// 目标: 将B组件中的数据传递给A组件
// 第一步:B组件中的数据 通过 子传父 传递给App组件
// 第二步:App组件 通过 父传子 将数据传递给A组件
function FunA (props) {
return (
<div>this is A:{props.msg}</div>
)
}
function FunB (props) {
const { getMsg } = props
const msg = '这是B组件数据'
return (
<div>this is B:
<button onClick={() => { getMsg(msg) }}>发送数据</button>
</div>
)
}
class App extends React.Component {
state = {
message: '这个是原始数据',
}
getMsg = (sonMsg) => {
console.log(sonMsg)
this.setState({
message: sonMsg
})
}
render () {
return (
<div className="app">
<FunA msg={this.state.message} />
<FunB getMsg={this.getMsg} />
</div >
)
}
}
export default App
跨组件传递数据:
import React, { createContext } from 'react'
// 目标: APP -> A -> C
// App 数据 -> c
// 1.导入createContext方法并执行
const { Provider, Consumer } = createContext()
function FunA () {
return (
<div>this is A:
<FunC />
</div>
)
}
function FunC () {
return (
<div>this is C:
{/* 3.通过Consumer 使用数据 */}
<Consumer>{(value) => <span>{value}</span>}</Consumer>
</div>
)
}
class App extends React.Component {
state = {
message: '父组件数据',
}
render () {
return (
// 2.使用Provider包裹根组件
<Provider value={this.state.message}>
<div className="app">
<FunA />
</div >
</Provider>
)
}
}
export default App
阶段练习:
import React from 'react'
// 子组件
function ListItem(props) {
const { name, price, info, id, delHandler } = props
return (
<div>
<h3>{name}</h3>
<p>{price}</p>
<p>{info}</p>
<button onClick={() => delHandler(id)}>删除</button>
</div>
)
}
// 父组件
class App extends React.Component {
state = {
list: [
{ id: 1, name: '超级好吃的棒棒糖', price: 18.8, info: '开业大酬宾,全场8折' },
{ id: 2, name: '超级好吃的大鸡腿', price: 34.2, info: '开业大酬宾,全场8折' },
{ id: 3, name: '超级无敌的冰激凌', price: 14.2, info: '开业大酬宾,全场8折' }
]
}
delHandler = (id) => {
this.setState({
list: this.state.list.filter(item => item.id !== id)
})
}
render() {
return (
<>
{
this.state.list.map(item =>
<ListItem
key={item.id}
{...item}
delHandler={this.delHandler}
/>
)
}
</>
)
}
}
export default App