前言
从官网上也有介绍组件间如何通信,但不够详细,这里做个小结,方便对比和回顾
本文内容
处理组件之间的通信, 主要取决于组件之间的关系,因此我们划分为以下三种:
- 【父组件】向【子组件】传值;
- 【子组件】向【父组件】传值;
- 【组件A】向无关系【组件B】传值,一般为兄弟组件;
一、「父组件」向「子组件」传值
这是最普遍的用法,实现上也非常简单,主要是利用props来实现
// 父组件 import React from 'react'; import Son from './components/son'; class Father extends React.Component { constructor(props) { // 这里要加super,否则会报错 super(props); this.state = { checked: true } } render() { return ( <Son text="Toggle me" checked={this.state.checked} /> ) } }
// 子组件 class Son extends React.Component { render() { // 接收来自父组件的参数 let checked = this.props.checked, text = this.props.text; return ( <label>{text}: <input type="checkbox" checked={checked} /></label> ) } }
多想一点:
如果组件的嵌套层次太多,那么从外到内的交流成本就会加深,通过 props 传值的优势就不明显,因此,我们还是要尽可能的编写结构清晰简单的组件关系, 既也要遵循组件独立原则,又要适当控制页面,不可能或极少可能会被单用的代码片,可不编写成一个子组件
二、「子组件」向「父组件」传值
我们知道,react的数据控制分为两种,为 props 和 state;其中,props 如上刚介绍过,它是父组件向子组件传值时作为保存参数的数据对象;而 state 是组件存放自身数据的数据对象。这两者最主要的区别就是,props属于父组件传给子组件的只读数据,在子组件中不能被修改,而state在自身组件中使用时,可以通过setState来修改更新。
子组件向父组件传值,需要控制自己的state,并发起父组件的事件回调来通知父组件
// 父组件 import Son from './components/son'; class Father extends React.Component { constructor(props) { super(props) this.state = { checked: false } } onChildChanged() { this.setState({ checked: newState }) } render() { let isChecked = this.state.checked "Toggle me" initialChecked={this.state.checked} callbackParent={this.onChildChanged.bind(this)} ></Son> </div> ) } }
// 子组件 class Son extends React.Component { constructor(props) { super(props); this.state = { checked: this.props.initialChecked } } onTextChange() { let newState = !this.state.check.checked; this.setState({ checked: newState }); // 注意,setState 是一个异步方法,state值不会立即改变,回调时要传缓存的当前值, // 也可以利用传递一个函数(以上传的是对象),并传递prevState参数来实现数据的同步更新 this.props.callbackParent(newState); } render() { let text= this.props.text; let checked = this.state.checked; return ( <label>{text}: <input type="checkbox" checked={checked} onChange={this.onTextChange.bind(this)}></label> ) } }
多想一点:
- 同样应当避免深层次的组件嵌套
- 这里其实是依赖了props来传递事件的引用,并通过回调的方式来实现,在没有使用工具情况下,可以使用该办法
拓展一点:
在onChange 事件或者其他React事件中,你能获取以下信息:
- 「this」 指向你的组件
- 「一个参数」 一个react合成事件, SyntheticEvent
我们知道,React对所有事件的管理都是自己封装实现的,html中的 onclick 被封装成了 onClick, onchange 被封装成了 onChange。从根本上来说,他们都是被绑定在body上的。
多个子组件回调同一个回调函数情况
父组件中大概率包含多个子组件,为节省和简洁代码,遵循 don't repeat yourself 原则,我们会让一个回调函数实现多个子组件的功能,或多个组件协作完成指定功能
import React from 'react'; import Son from './components/son'; class Father extends React.Componnet { constructor(props) { super(props); this.state = { totalChecked: 0 } } onChildChangeed() { let newTotal = this.state.totalChecked + (new State "Toggle me" initialChecked={this.state.checked} callbackParent={this.onChildChanged} /> <Son text="Toggle me too" initialChecked={this.state.checked} callbackParent={this.onChildChanged} /> <Son text="Add me" initialChecked={this.state.checked} callbackParent={this.onChildChanged} /> </div> ) } }
// 子组件 class Son extends React.Component { constructor(props) { super(props); this.state = { checked: this.props.initialChecked } } onTextChange() { let newState = !this.state.checked; this.setState({ checked: newState }) // setState异步方法问题,注意传值 this.props.callbackParent(newState); } render() { let text = this.props.checked; let checked = this.state.checked; return { <label>{text}: <input type="checkbox" checked={checked} onChange={this.onTextChange.bind(this)} /></label> } } }
多想一点:
在本案例中,我们引用了三个 Son 子组件, 每个 Son 组件都独立工作互不干扰,该例中,增加了一个 totalChecked 来替代之前的 checked, 当组件触发onTextChange 后,触发父组件的回调函数使得父组件的值得以改变。
三、组件A和无关系组件B之间的通信
如果组件之间没有任何关系,或者组件嵌套的层次比较深,或者,你为了一些组件能够订阅,写入一些信号,不想让两个组件之间插入一个组件,而是让两个组件出于独立的关系。对于时间系统,有两个基本操作:
- 订阅: subscribe
- 监听: listen
并发送 send / 触发 trigger / 发布 publish / 发送 dispatch 通知那些想要的组件
1. Event Emitter/Target/Dispatcher
特点: 需要一个指定的订阅源
// to subscribe otherObiect.addEventListener('clickEvent', function() { alert('click!'); }) // to dispatch this.dispatchEvent('clickEvent');
2. Publish / Subscribe
特点: 触发的时候,不需要指定一个特定的源,使用全局对象广播的方式来处理事件
// to subscribe globalBroadcaster.subcribe('clickEvent', function() { alert('cilck!'); }) // to publish globalBroadcaster.publish('clickEvent');
这种方案还有一个插件可用, 即 PubSubJs;用法如下:
import Pubsub from 'pubsub-js'; ... // to subscribe Pubsub.subscribe('EVENT', (msg, param) => { console.log(msg, param); }); // to publish Pubsub.publish('EVENT', param);
3. Single
特点: 与 Event Emitter/Target/Dispatcher
类似,但是不要使用随机字符串作为事件触发的引用。触发事件的每一个对象都需要一个确切的名字,并且在触发的时候,也必须要指定确切的事件
// to subscribe otherObject.clicked.add(function() { alert('click'); }) // to dispatch this.clicked.dispatch();
React 团队使用的是:js-signals 它基于 Signals 模式,用起来相当不错。
事件订阅与取消
使用React事件的时候,必须关注以下两个方法:
- componentDidMount
- componentWillUnmount
在 componentDidMount 事件中,等待组件挂载 mounted 完成,再订阅事件;订阅的事件需要在组件卸载 componentWillUnmount 的时候取消事件的订阅。
因为组件的渲染和销毁是有 React 来控制的,我们不知道怎么引用他们,所以EventEmitter 模式在处理事件的时候用处不大,Pub/Sub 模式就好用些,因为我们不需要知道引用在哪。
ES6策略: yield and js-csp
ES6中有一种传递信息的方式,使用生成函数 generators 和 yield 关键字,用法参考以下例子
import csp from 'js-csp'; function* list() { for(var i = 0; i< arguments.length; i++) { yield arguments[i]; } return "done"; } var o = list(1, 2, 3); var cur = o.next; while (!cur.done) { cur = o.next(); console.log(cur); }
结束语
数据在组件中应该以什么样的方式进行传递取决于组件之间存在什么样的关系和当时的业务场景需求,大家应该根据项目合理选择数据处理的方案,这很可能减少你大量的代码量和代码逻辑。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
React,组件间通信
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】