一、 父子组件(类组件和函数组件中都可)
-
父传子
// 父组件 import React, { Component } from "react"; import Child from "./Child"; export default class Parent extends Component { constructor(props) { super(props); this.state = { msg: "我是父组件的信息", }; } render() { return ( <div> // 父组件直接通过属性传递给子组件 <Child msg={ this.state.msg}></Child> </div> ); } } // 子组件 import React, { Component } from "react"; // 子组件 export default class Child extends Component { render() { // 子组件通过props接收父组件传递的值 console.log(this.props); return ( <div> // 子组件使用 <p>{ this.props.msg}</p> </div> ); } }
-
子传父
// 父组件 class Parent extends React.Component { constructor(props) { super(props); this.state = { parentMsg: "", }; } // 提供回调函数 接收子组件数据 getChidMsg = (msg) => { console.log("子组件的数据", msg); this.setState({ parentMsg: msg, }); }; render() { return ( <div> 父组件:{ this.state.parentMsg} <br /> 子组件: <Child getMsg={ this.getChidMsg}></Child> </div> ); } } // 子组件 class Child extends React.Component { constructor(props) { super(props); this.state = { msg: "子组件的值", }; } // 子组件调用父组件中传递的回调函数 handClick = () => { this.props.getMsc(this.state.msg); }; render() { return ( <div> <button onClick={ this.handClick}> 点击我 </button> </div> ); } }
二、 跨组件
如果目的子组件在组件嵌套的深层,直接用 props 传值是不实际的。
- context(组件树中从上到下,父到子)
redux 的原理就是用 context 进行数据传输。
// 使用context实现跨组件通信
import React, {
createContext } from "react";
// 1. 创建Context对象
const Context = createContext();
function A() {
return (
<div>
<B></B>
<Context.Consumer>{
(value) => <span>{
value}</span>}</Context.Consumer>
</div>
);
}
function B() {
// 3. 通过Comsumer获取数据
return (
<div>
<Context.Consumer>{
(value) => <span>{
value}</span>}</Context.Consumer>
</div>
);
// 4. react16.8版本之后增加了hooks,可以使用hooks中的useContext来获取消费者
import {
useContext } from "react";
const {
message } = useContext(Context);
// 直接这样定义就可以拿到consumer的值,省去了之前要定义在Consumer中才能使用。
}
class App extends React.Component {
state = {
message: "要传递的消息",
};
render() {
return (
// 2. 使用provider包裹根组件
<Provider value={
this.state.message}>
<div>
<A></A>
</div>
</Provider>
);
}
}
- PubSub
- 下载
npm install pubsub-js --save
- 发送数据:
import PubSub from "pubsub-js";
// 接收二个参数,第一个是要发送的消息,让订阅,第二个是传输的数据。
Pubsub.publish("updateSelectedKey", key);
- 接收数据:
import PubSub from "pubsub-js";
// 组件加载完成时,订阅
componentDidMount() {
this.pubsub = PubSub.subscribe('updateSelectedKey', (msg, key) => {
this.setState({
currentRoute: key
});
})
}
// 取消订阅
componentWillUnmount() {
PubSub.unsubscribe(this.pubsub);
}
-
ref
import React, { Component, createRef, useRef } from 'react'; import Child from './child'; class Parent extends Component { constrator(props) { super(props); this.state = { name: '' } // 1.创建ref this.childRef = createRef(); } // 函数组件 // const childRef = useRef(); componentDidMount() { // 3.获取ref // 如果是自定义组件,获取到是组件实例 // 如果是dom元素,获取到是dom节点 console.log(this.childRef.current); // 4.子传父 this.setState({ name: this.childRef.current.name }) // 5.父传子 this.childRef.current.setName('ShangQiao') } render() { return { <div> <!-- 2.绑定ref --> <Child ref={ this.childRef}></Child> </div> } } }
-
forwardRef
// 子组件(通过forwardRef方法创建)
const Child = React.forwardRef((props, ref) => <input forwardRef={
ref} />);
// 父组件
class Father extends React.Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount() {
console.log(this.myRef.current);
}
render() {
return <Child ref={
this.myRef} />;
}
}
注意:
- ref 在函数式组件上不可使用,函数式组件无实例,但是其内部的 dom 节点和类组件可以使用;
- 可以通过 ReactDOM.findDOMNode(),入参是一个组件或 dom 节点,返回值的组件对应的 dom 根节点或 dom 节点本身。
通过 refs 获取到组件实例后,可以通过此方法来获取其对应的 dom 节点;
- redux