react组件之间传值

    看过一些文章介绍react组件之间传值,无外乎以下几种情况:父子组件之间相互传值,兄弟节点之间传值。最常见的就是父子组件,做法也很简单:就是在父组件中直接通过props属性的方式将函数或者值传给子组件。父组件有变化,相应的值就会体现在子组件中;子组件有动作发生,则调用函数,函数是父组件传递过来的,父组件就能获取子组件的值。

    还有一种情况,就是兄弟节点之间要传值,这个还比较复杂,因为他们之间没有直接的交集,但是他们有一个共同的父组件,可以借助父组件传递值,所以还是回到了父子组件传值上。

    这里有个需求:有一个菜单列表,点击菜单会选择相应的选项,有一个标签页选项,点击标签可以切换选项。菜单和标签页可以产生一种联动,他们是两个兄弟节点,现在需要考虑的是选择菜单,标签页也跟着动,标签页选择的时候,菜单也跟着响应,这个示例可以很好的演示多种情况传值,效果如下所示:

    

    代码部分:

import React,{useState} from 'react'
import {Tabs,Menu,Divider} from 'antd'
import 'antd/dist/antd.css'
const {TabPane}  = Tabs

const MenuList = (props)=>{
	const {current,setCurrent} = props;
	const handleClick = e =>{
		setCurrent(e.key)
	}
	return <Menu onClick = {handleClick} selectedKeys = {current} >
				<Menu.Item key="a">aaa</Menu.Item>
				<Menu.Item key="b">bbb</Menu.Item>
				<Menu.Item key="c">ccc</Menu.Item>
			</Menu>
}

const TabComponents = (props)=>{
	const {activeKey,setActiveKey} = props;
	const changeTabHandler = (key)=>{
		setActiveKey(key)
	}
	return <Tabs activeKey={activeKey} onTabClick = {changeTabHandler}>
				<TabPane tab="aaa" key="a">this is aaa</TabPane>
				<TabPane tab="bbb" key="b">this is bbb</TabPane>
				<TabPane tab="ccc" key="c">this is ccc</TabPane>
		   </Tabs>
}
const MyTabs = ()=>{
	const [activeKey,setActiveKey] = useState('a')
	return <div>
		<MenuList setCurrent = {setActiveKey} current={activeKey}/>
		<Divider/>
		<TabComponents activeKey = {activeKey} setActiveKey = {setActiveKey}/>
	</div>
}

export default MyTabs

    这里使用了antd中的Menu和Tabs控件形成MenuList和TabComponents,他们组成一个新的组件MyTabs,在父组件中,我们通过useState函数定义了一个变量和设置变量的方法,分别对应activeKey,setActiveKey,最终将他们都传入MenuList和TabComponents中。

    这种做法,达到了联动的效果,却破坏了Tabs默认的onTabClick事件,本来Tabs的切换是根据用户点击来做切换标签页,但是现在变成了既可以手动也可以自动,手动就是,用户点击菜单选项,通过外部传入值,切换tab,这里是通过改变默认值activeKey的方式实现,如果我们不添加onTabClick函数响应,那么用户点击标签页会失效。

    ==========================================================================

    还有一种做法,可以通用,不仅可以父子之间,还可以是兄弟节点之间传值,就是发布订阅模式。这种方式,不需要父节点来维护值的状态,因此也不需要通过props属性传值,直接在需要传值的组件之间来通过发布订阅即可。组件内部自己维护状态的改变,而且这种方式也是可以双向的传值。

    先上效果图,跟上面没什么两样:

    

    代码需要增加一个简单的发布订阅实现:

    EventEmmiter.js

const EventEmmiter = {
	_events:{},
	dispatch:function(event,data){
		if(!this._events[event])
			return;
		for(var i=0;i<this._events[event].length;i++)
		{
			this._events[event][i](data);
		}
	},
	subscribe:function(event,callback){
		if(!this._events[event])
			this._events[event] = []
		this._events[event].push(callback)
	}
}
export default EventEmmiter

    PubSub.js

import React,{useState} from 'react'
import {Menu,Tabs,Divider} from 'antd'
import EventEmmiter from '../utils/EventEmmiter'
import 'antd/dist/antd.css'
const {TabPane} = Tabs
const MenuList = (props)=>{
	const [current,setCurrent] = useState('a');
	const clickHandler = (e)=>{
		EventEmmiter.dispatch('changeTab',e.key)
		setCurrent(e.key)
	}
	EventEmmiter.subscribe('changeMenu',(key)=>{
		setCurrent(key)
	})
	return <Menu onClick = {clickHandler} selectedKeys = {current}>
		<Menu.Item key="a">aaa</Menu.Item>
		<Menu.Item key="b">bbb</Menu.Item>
		<Menu.Item key="c">ccc</Menu.Item>
	</Menu>
}

const TabComponent = (props)=>{
	const [current,setCurrent] = useState('a');
	const clickHandler = (e)=>{
		EventEmmiter.dispatch('changeMenu',e)
		setCurrent(e)
	}
	EventEmmiter.subscribe('changeTab',(key)=>{
		setCurrent(key)
	})
	return <Tabs activeKey={current} onTabClick = {clickHandler}>
		<TabPane key="a" tab="xxx">xxx this is aaa.</TabPane>
		<TabPane key="b" tab="yyy">yyy this is bbb.</TabPane>
		<TabPane key="c" tab="zzz">zzz this is ccc.</TabPane>
	</Tabs>
}

const PubSub = ()=>{
	return <div>
		<MenuList/>
		<Divider/>
		<TabComponent/>
	</div>
}

export default PubSub

     这种方式比起前面,代码量虽然有增加,但是它却是一种通用的做法,不用考虑组件的关系。发布订阅是分开的,他们各自作用在不同的组件里面,是成对出现的。

 

React 中,有多种方式可以实现组件之间的值传递。以下是一些常见的方式: 1. Props(属性):通过在父组件中给子组件传递属性,子组件可以通过 props 对象来获取这些属性值。父组件中的属性变化会触发子组件的重新渲染。 2. State(状态):每个组件都有自己的状态对象,可以通过 setState 方法来更新状态并触发重新渲染。父组件可以通过 props 将状态值传递给子组件,并通过回调函数来修改父组件的状态。 3. Context(上下文):Context 提供了一种在组件树中共享数据的方式,可以在父组件中创建一个 Context 对象,并通过 Provider 组件将数据传递给子组件。子组件可以通过 Consumer 组件useContext 钩子来访问这些数据。 4. Redux 或其他状态管理库:使用 Redux 或其他状态管理库可以将应用的状态集中管理,并通过提供的 API 来进行状态的读取和更新。这样不同组件之间可以共享和传递状态,而不需要通过 props 层层传递。 5. 发布订阅模式或事件总线:可以使用发布订阅模式或事件总线来实现组件之间的解耦和通信。一个组件可以发布一个事件,其他组件可以订阅该事件并执行相应的操作。 这些是常见的组件传值方式,选择哪种方式取决于具体的场景和需求。在实际开发中,根据项目的规模和复杂度,选择合适的方式来进行组件间的数据传递。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值