组件之间进行通信是开发过程中最最常用的,在进行组件通信之前,你要了解,组件间的关系都有哪些呢?
- 父子组件
- 兄弟组件(非嵌套组件)
- 祖孙组件(跨级组件)
那么基于这些组件关系,又会有哪些通信方式呢?不同的通信方式适用于哪些组件关系?接下来我们一一探讨: 先总结通信方式:
- props (1. children props 2. render props)
props通常是使用在父子组件中,只需要通过标签属性的方式很方便的进行将数据从父组件传递给子组件。 例如: 在父组件中
import React, {Component,Fragment} from 'react';
import './index.css'
import Item from "../Item";
class List extends Component {
state = {
tip:"none"
}
render() {
var {tip} = this.state
return (
<Fragment>
<Item tip={tip}/>
</Fragment>
);
}
}
export default List;
在子组件中通过this.props.tip 即可获取父组件传过来的参数。
那么如何将信息在子组件中传给父组件呢?这时我们可以在父组件中传递一个函数给子组件,子组件在合适的时候调用此函数,进行传值。即可实现子传父。 例如: 父组件
import React, {Component,Fragment} from 'react';
import './index.css'
import Item from "../Item";
class List extends Component {
state = {
tip:"none"
}
changePar=(e)=>{
console.log("子组件调用父组件传过来的值",e)
this.setState({
tip:"block"
})
}
render() {
var {tip} = this.state
return (
<Fragment>
<Item info={this.changePar} tip={this.state.tip}/>
</Fragment>
);
}
}
export default List;
子组件:
import React,{Fragment} from 'react';
class Item extends React.PureComponent {
dealProps = () => {
this.props.info("子传父")
}
render() {
return (
<Fragment key="item">
<span onClick={this.dealProps}>父组件通过props传过来的值:{this.props.tip}</span>
</Fragment>
)
}
}
export default Item;
props传递还有一种方式,那就是render props 看示例:
import React, {Component} from 'react';
import './index.css'
export default class Footer extends Component {
render() {
return (
<div className="Footer">
Footer
<A render={(name)=><B name={name}/>}>
Hello
</A>
</div>
);
}
}
class A extends Component {
state = {
name:"小聂"
}
render() {
console.log(this.props)
var {name} = this.state
return (
<div className="A">
这是A组件
{this.props.children}
{this.props.render(name)}
</div>
)
}
}
class B extends Component {
render() {
return (
<div className="B">这是B组件:{this.props.name}</div>
)
}
}
- 消息订阅与发布
pubs-sub、event等 在非父子组件的情况下,如果继续使用props传递参数要么逻辑不可行要么就是太麻烦,所以此时我们可以通过第三方插件,例如pubs-sub来实现消息的订阅与发布:
1. 工具库:PubSubJS
2. 安装:npm i pubsub-js
3. 兄弟组件之间,一个订阅消息、一个发布消息,即可将信息从发布端发送到接收端
4. 使用:
1). import PubSub from 'pubsub-js'
2). PubSub.subscribe('delete',function(data){})
3). PubSub.publish('delete',data)
发布消息的组件:
import React, {Component} from 'react';
import PubSub from 'pubsub-js'
class Header extends Component {
sendInfo = () => {
console.log("执行发送")
PubSub.publish("key","我是发出的消息")
}
render() {
return (
<div>
<span onClick={this.sendInfo}>发布消息</span>
</div>
);
}
}
export default Header;
订阅消息的组件:
import React, {Component} from 'react';
import PubSub from 'pubsub-js'
import './index.css'
export default class Footer extends Component {
componentDidMount() {
this.toekn = PubSub.subscribe('key',(_,data)=>{
console.log('兄弟组件收到信息:',data)
})
}
componentWillUnmount() {
PubSub.unsubscribe(this.token)
}
}
- 集中式管理:
redux、dva等 可参考文章: React之redux的使用(精简版) React 之redux的使用(完整版) - conText:
生产者-消费者模式
import React, {Component} from 'react';
import './index.css'
const UserInfoContext = React.createContext()
export default class Footer extends Component {
state = {
userInfo:{
name:"小小",
gender:1
}
}
render() {
const {userInfo} = this.state
return (
<div className="Footer">
Footer
{}
<UserInfoContext.Provider value={userInfo}>
<A></A>
</UserInfoContext.Provider>
</div>
);
}
}
class A extends Component {
render() {
return (
<div className="A">
这是A组件
<B/>
</div>
)
}
}
class B extends Component {
static contextType = UserInfoContext
render() {
console.log(this.context)
return (
<div className="B">这是B组件:{this.props.name}</div>
)
}
}
function B() {
return(
<div className="B">
B组件
{}
<UserInfoContext.Consumer>
{
value => {
console.log(value)
return `姓名是${value.name},性别是${value.gender}`
}
}
</UserInfoContext.Consumer>
</div>
)
}
不同组件关系与通信方式的搭配:
- 父子组件: props
- 兄弟组件:消息订阅-发布、集中式管理
- 祖孙组件(跨级组件):消息订阅-发布、集中式管理、conText(这种方式开发比较少用,封装插件用的比较多)
|