今天我们单独聊一聊React中组件之间的传值问题!!!
一、父组件向子组件传值
//父组件
class App extends React.PureComponent<AppProps> {
render() {
return (
<div>
<Title title="标题" type="food" url="http://www.baidu.com" />
</div>
)
}
}
//子组件
const Title = ({ title = '默认标题', type = '', url = '' }) => (
<div className="title-container">
<div>{title}</div>
<div>{url}</div>
<div>{type}</div>
</div>
解析:父组件中直接在调用的子组件上绑定要传的属性值,子组件中通过props接受父组件传过来的值,由于上述例子是函数组件写法,故没有明写props用法,但实际是一样的
二、子组件向父组件传值
//子组件
const Title = ({ title = '默认标题', type = '', url = '',onClick }) => (
<div className="title-container">
<div>{title}</div>
<div>{url}</div>
<div>{type}</div>
<button onClick={() => onClick(123)}>点我测试</button>
</div>
//父组件
class App extends React.PureComponent<AppProps> {
onClick = val => {
console.log(val); //123
}
render() {
return (
<div>
<Title title="标题" type="food" url="http://www.baidu.com" onClick={this.onClick}/>
</div>
)
}
}
解析:子组件要想向父组件传递一个123,只需要调用父组件传给它的方法,将值放入方法的的入参中,这样子组件在点击按扭时,就会调用父组件中的方法,然后父组件中就能在方法中通过入参来接受到这个从子组件那传过来的值
三、爷组件向孙组件传值
在一个典型的 React 应用中,数据是通过 props 属性由上向下(由父及子)的进行传递的(就如同上述一样),但如果组件套的很深的话,这样传递就非常恶心了。解决办法一般有两种:
-
Redux
通过Redux的方式,把需要传递的数据放到store里,在需要用到的组件通过this.props获取,如对Redux还有不太了解的同学可以参考我的另一篇文章:Redux -
通过 Context 传递 =》好的,接下来我们来介绍一下这个特性Context
我们知道,在JS中context指的是函数的执行上下文,函数被调用时,this指向谁,谁就是当前的执行 上下文;
react中的context是什么呢?官方文档给出:
Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。
文档也没具体给出context到底是什么,而是告诉我们context能干什么,也就是说,如果我们不想通过 props实现组件树的逐层传递数据,则可以使用context实现跨层级进行数据传递!
如何使用 Context 呢?
context api给出三个概念:React.createContext()、Provider、Consumer;- React.createContext()
这个方法用来创建context对象,并包含Provider、Consumer两个组件 <Provider />、<Consumer /> const {Provider, Consumer} = React.createContext();
- Provider
数据的生产者,通过value属性接收存储的公共状态,来传递给子组件或后代组件 eg: <Provider value={/* some value */}>
- Consumer
数据的消费者,通过订阅Provider传入的context的值,来实时更新当前组件的状态 eg: <Consumer> {value => /* render something based on the context value */} </Consumer>
值得一提的是每当Provider的值发生改变时, 作为Provider后代的所有Consumers都会重新渲染
代码示例:
import React from 'react' import ReactDOM from 'react-dom' // 创建一个 textcont 特性的 const {Provider,Consumer} = React.createContext('顶顶顶') class Person extends React.Component{ constructor(props){ super(props) this.state = { color : 'red' } } render(){ return ( <Provider value={this.state.color}> <h1>我是父组件</h1> <Son></Son> </Provider> ); } } class Son extends Person{ render(){ return <div> <h3>我是子组件</h3> <Son1></Son1> </div> } } class Son1 extends Son{ render(){ return ( <Consumer> { (color) => <div> <h6 style={{color}}>我是孙子组件-----{color}</h6> </div> } </Consumer> ); } } ReactDOM.render(<div> <Person></Person> </div>,document.getElementById('app'))
最终效果如下所示:
四、兄弟组件间的传值(消息订阅、发布模式)
- 方式一:events模块
// 兄弟1组件中进行发送名为message的事件
import {EventEmitter} from 'events' //引入events模块
const bus = new EventEmitter(); //创建一个events实例
bus.emit('message',{ // 通过实例中的一个emit方法进行发送事件,事件名为message,内容为一个包含name和age的对象
name:'haha',
age:12
})
// 兄弟2组件
import {EventEmitter} from 'events'
const bus = new EventEmitter();
bus.on('message',(data)=>{ //通过实例中的on方法来订阅名为message的事件,一旦兄弟1组件中发布了,这里就能监听到,拿到具体的data
console.log(data)
})
2、方式二、PubSubJs工具库
// 兄弟1组件,发布msg事件,并传递data数据
import PubSub from “pubsub-js”
PubSub.publish('msg',data)
// 兄弟2组件,订阅msg事件,接受data数据
import PubSub from “pubsub-js”
PubSub.subscribe('msg',(data)=>{
console.log(data)
})