父子组件通信—Props传递数据和方法
父级组件将数据和方法以props形式传递给子组件供子组件使用
import React,{ Component } from "react";
import Sub from "./Sub.js";
import "./App.css";
export default class App extends Component{
constructor(props){
super(props)
this.getCount = this.getCount.bind(this)
}
getCount(count){
console.log(count);
}
render(){
return(
<div>
<Sub title = "今年过节不收礼"
getCount = { this.getCount }
/>
</div>
)
}
}
import React,{ Component } from "react";
class Sub extends Component{
constructor(props){
super(props)
this.sendCount = this.sendCount.bind(this)
}
state = { count:0 }
sendCount(){
//调用父级组件传入的方法
this.props.getCount(this.state.count)
}
return(
const props = this.props
<div>
<h1> { props.title } </h1> //从父组件接受props信息展示
<button onClick = { this.sendCount }>
Click Me //将子组件信息传给父组件供使用
</button>
</div>
)
}
export default Sub;
兄弟组件通信—状态提升
将数据和操作数据的方法,放在兄弟组件共同的父级组件上,也就是状态提升。
跨级组件通信—Context
跨级组件通信,就是父组件向子组件的子组件通信,向更深层的子组件通信。跨级组件通信可以采用下面两种方式:
- 中间组件层层传递 props
- 使用context对象
对于第一种方式,如果父组件结构较深,那么中间的每一层组件都要去传递 props,增加了复杂度,并且这些 props 并不是这些中间组件自己所需要的。
使用 context 是另一种可行的方式,context 相当于一个全局变量,是一个大容器,我们可以把要通信的内容放在这个容器中,这样一来,不管嵌套有多深,都可以随意取用。
import React,{ Component } from "react";
import Sub from "./Sub.js";
import "./App.css";
export default class App extends Component{
constructor(props){
super(props)
this.getCount = this.getCount.bind(this)
}
// 上级组件声明自己支持 context
static childContextTypes = {
color:PropTypes.string,
getCount:PropTypes.func,
}
// 父组件提供一个函数,用来返回相应的 context 对象
getChildContext(){
return{
color:"red",
getCount:this.getCount.bind(this)
}
}
getCount(count){
console.log(count);
}
render(){
return(
<div>
<Sub title = "今年过节不收礼"
getCount = { this.getCount }
/>
</div>
)
}
}
import React,{ Component } from "react";
class Sub extends Component{
constructor(props){
super(props)
this.sendCount = this.sendCount.bind(this)
}
// 下级组件声明自己需要使用context 不接收就获取不到context对象
static contextTypes = {
color:PropTypes.string,
getCount:PropTypes.func,
}
state = { count:0 }
sendCount(){
//使用context使用接受到的方法
this.context.getCount(this.state.count);
}
return(
const props = this.props
<div>
<h1> { props.title } </h1> //从上级组件接受props信息展示
<button onClick = { this.sendCount }>
Click Me //将下级组件信息传给父组件供使用
</button>
</div>
)
}
export default Sub;
任意组件间通信—PubSub
没有任何包含关系的组件,包括兄弟组件以及不在同一个父级中的非兄弟组件。对于非嵌套组件,可以采用下面两种方式:
- 利用二者共同父组件的 context 对象进行通信
- 使用消息订阅发布机制进行通信
首先,需要在项目引入PubSub库
npm install pubsub-js --save
其次,需要在组件中引入PubSub,并做好消息订阅与发布
import React, { Component } from 'react'
import PubSub from 'pubsub-js'
class Publish extends Component{
constructor(props){
super(props)
this.sendCount = this.sendCount.bind(this)
}
state = { count:0 }
sendCount(){
//发布消息
PubSub.publish('sendCount',{isLoading:false,users:response.data.items})
}
return(
const props = this.props
<div>
<h1> { state.xxxx } </h1>
<button onClick = { this.sendCount }>
Click Me //发布消息
</button>
</div>
)
}
export default Publish;
import React, { Component } from 'react'
import PubSub from 'pubsub-js'
class Subscribe extends Component{
constructor(props){
super(props)
state = { count:0 }
this.setCount = this.setCount.bind(this)
}
setCount(){}
componentDidMount(){
//订阅消息
this.token = PubSub.subscribe('sendCount',(_,stateObj)=>{
//回调函数接收两个参数,消息名&&消息内容
//必须使用箭头函数或者正确bind this的函数this.setCount
this.setState(stateObj)
})
}
componentWillUnmount(){
//组件取消挂载时,取消订阅
PubSub.unsubscribe(this.token);
}
return(
const props = this.props
<div>
<h1> { state.count } </h1>
</div>
)
}
export default Subscribe;
任意组件间通信—集中式状态管理
React中数据通信是单向的,即父组件可以通过props向子组件传递数据,而子组件却不能向父组件传递数据。要实现子组件向父组件传递数据的需求,需要父组件提供一个修改数据的方法,当页面越来越多的时候,数据的管理就会变得异常复杂。
Redux是由Dan Abramov开源的一款前端状态管理框架,Redux将状态管理分为Action、Store和Reducers三部分。其中,Redux将应用程序的状态存储到Store中,组件通过dispatch()方法触发Action,Store接收Action并将Action转发给Reducer,Reducer根据Action类型对状态数据进行处理并将处理结果返回给Store,其他组件通过订阅Store状态的来刷新自身的状态。
如图所示,即为React原理
参考
- https://www.jianshu.com/p/fb915d9c99c4 React组件间通信的几种方式
- https://zhuanlan.zhihu.com/p/89015701 React使用PubSub实现消息订阅发布
- https://github.com/mroderick/PubSubJS PubSub Github仓库地址
- https://www.cxyzjd.com/article/sinat_17775997/82692621 PubSub回调函数bind this
- https://cloud.tencent.com/developer/article/1817831
- https://juejin.cn/post/7031509723190919175 Redux集中式状态管理
- https://segmentfault.com/a/1190000039419540 Redux实践1