目录
组件通信的意义
父传子实现
?props说明
?子传父实现
兄弟组件通信
跨组件通信Context?
组件通信的意义
组件是独立封闭的单元,默认情况下只能使用自己的数据(state)
组件开发的过程中,完整的功能会拆分多个组件,在这个过程中不可避免的需要互相传递一些数据为了能让各组件之间可以进行互相沟通,数据传递,这个过程就是组件通信。
1.父子关系 --- 最重要的
2.兄弟关系 --- 自定义事件模式产生技术方法/通过共同的父组件通信
3.其它关系 --- mobx/ redux / 基于hook的方案
父传子实现
实现父子通信中的父传子,把父组件中的数据传给子组件
实现步骤:
1.父组件提供要传递的数据 --- state
2.给子组件标签添加属性值为state中的数据
3.子组件中通过props接收父组件中传过来的数据
? ? ? ? 1.类组件使用this.props获取props对象
? ? ? ? 2.函数式组件直接通过参数获取props对象
例↓
import React from "react";
// App父组件 Son子组件
//函数式的Son子组件
function SonF(props) {
// props是一个对象 里面存在通过父组件传入的所有数据
return <div>我是函数式子组件,{props.msg}</div>;
}
//类组件的Son子组件
class SonC extends React.Component {
render() {
return (
// 类组件必须通过this关键词去获取,这里的props是固定的
<div>我是类子组件,{this.props.msg}</div>
)
}
}
class App extends React.Component {
//准备数据
state = {
message:'今天星期三'
}
// eslint-disable-next-line react/require-render-return
render() {
return (
<div>
{/* 子组件身上绑定属性 属性名可自定义 保持语义化 */}
<SonF msg={this.state.message} />
<SonC msg={this.state.message} />
</div>
);
}
}
export default App;
?props说明
1.props是只读对象(readonly)
根据单向数据流的要求,子组件只能读取props中的数据,不能进行修改
2.props可以传递任意数据
数字、字符串、布尔值、数组、对象、函数、JSX
数组、对象、函数props传值示例↓
import React from "react";
// App父组件 Son子组件
//函数式的Son子组件
function SonF(props) {
console.log(props);
// props是一个对象 里面存在通过父组件传入的所有数据
return (
<div>
我是函数式子组件,
{props.list.map((item) => (
<p key={item}>{item}</p>
))},
{props.person.name},
<button onClick={props.getMessage}>触发父组件传入的函数</button>
</div>
);
}
class App extends React.Component {
//准备数据
state = {
list: [1, 2, 3],
person: {
name: "凤凰火",
age: 22,
},
};
getMessage = ()=>{
console.log('父组件中的函数')
}
// eslint-disable-next-line react/require-render-return
render() {
return (
<div>
{/* 子组件身上绑定属性 属性名可自定义 保持语义化 */}
<SonF list={this.state.list} person={this.state.person} getMessage={this.getMessage} />
</div>
);
}
}
export default App;
?JSX类型props传值示例↓
import React from "react";
// App父组件 Son子组件
//函数式的Son子组件
function SonF(props) {
console.log(props);
// props是一个对象 里面存在通过父组件传入的所有数据
return (
<div>
{props.jsx}
</div>
);
}
class App extends React.Component {
//准备数据
// eslint-disable-next-line react/require-render-return
render() {
return (
<div>
{/* 子组件身上绑定属性 属性名可自定义 保持语义化 */}
<SonF jsx={<span>jsx传值</span>} />
</div>
);
}
}
export default App;
?子传父实现
子组件调用父组件传递过来的函数,并且把想要传递的数据当成函数的实参
子传父:子组件调用父组件传递过来的函数,并且把想要传递的数据当成函数的实参
?示例↓
import React from "react";
// App父组件 Son子组件
// //函数式的Son子组件
// function SonF(props) {
// console.log(props);
// // props是一个对象 里面存在通过父组件传入的所有数据
// return (
// <div>
// 这是子组件<br/>
// <button onClick={()=>props.getMessage('这是来自子组件中的数据')}>按钮</button>
// </div>
// );
// }
//函数式的Son子组件
function SonF(props) {
console.log(props);
// props是一个对象 里面存在通过父组件传入的所有数据
// 解构写法
const {getMessage} = props;
return (
<div>
这是子组件<br/>
<button onClick={()=>getMessage('这是来自子组件中的数据')}>按钮</button>
</div>
);
}
class App extends React.Component {
//准备数据
// eslint-disable-next-line react/require-render-return
getMessage = (sonMsg)=>{
console.log(sonMsg)
}
render() {
return (
<div>
{/* 子组件身上绑定属性 属性名可自定义 保持语义化 */}
<SonF getMessage={this.getMessage} />
</div>
);
}
}
export default App;
兄弟组件通信
?通过状态提升机制,利用共同的父组件实现兄弟通信。
import React from "react";
//目标:B组件中的数据传给A
//技术方案:
//1.先把B中的数据通过子传父 传给App
//2.再把App接收到的Son中的数据 通过父传子传给A
function SonA(props: any) {
return (
<div>AAAAAAAAA{props.sendAMsg}</div>
)
}
function SonB(props: any) {
const bMsg = '这是B组件中的数据';
return (
<div>BBBBBBBBBB<button onClick={() => props.getBMsg(bMsg)}>发送数据</button></div>
)
}
class App extends React.Component {
state = {
sendAMsg: '父传子测试'
}
//声明一个传给B组件的方法
getBMsg = (msg: any) => {
console.log(msg)
//把msg数据交给sendAMsg
this.setState({
sendAMsg: msg
})
}
render() {
return (
<div>
<SonA sendAMsg={this.state.sendAMsg} />
<SonB getBMsg={this.getBMsg} />
</div>
)
}
}
export default App;
?点击后↓:
跨组件通信Context?
Context 提供了无需为每层组件手动添加props,就能在组件树间进行数据传递的方法。
实现步骤:
1.创建Context对象,导出Provider和Consumer对象
const { Provider, Consumer } = createContext()
2.使用Provider包裹根组件提供数据
<Provider value = {this.state.message}>
? ? ? ? {/*根组件*/}
</Provider>
3.需要用到数据的组件使用Consumer包裹获取数据
<Consumer>
? ? ? ? {value => /* 基于context值进行渲染 */}
</Consumer>
import React, { createContext } from "react";
// App -> A -> B
// App数据 -> B
// 1.导入createContext方法并执行
const defaultValue = ''
const { Provider, Consumer } = createContext(defaultValue);
function ComA() {
return (
<div>
AAAAAA
<ComB />
</div>
);
}
function ComB() {
return (
<div>
BBBBBB
{/* 3.通过Consumer使用数据 */}
<Consumer>{value => <span>{value}</span>}</Consumer>
</div>
);
}
class App extends React.Component {
state = {
message: "hello~",
};
render() {
return (
//2.使用provider包裹根组件
<Provider value={this.state.message}>
<div>
<ComA />
</div>
</Provider>
);
}
}
export default App;
?App根组件直接传值给子孙组件<ComB/>↑
|