组件之间的传值

组件之间的传值,包括父子组件传值, 兄弟组件之间的传值,其中父子组件包括父组件向子组件传值和子组件向父组件传值,现在一一来介绍一下.

一.父组件向子组件传值

    父组件通过state向子组件传值, 

// 父组件

constructor(props){

    super(props);

    this.state = { name : 'yuxi' }}

render(){ return 我是子组件 }

// 子组件

constructor(props){

super(props)

}

render(){

return <div>{this.props.name}<div>

}

二.子组件向父组件传值

    有三种方式实现子组件向父组件传值. 

(一)父组件通过state传值给子组件,子组件通过props获取父组件的传递值

    //(一)传值,即在父组件中声明好自己的state,然后传值,如下//1.初始值constructor() {

    super();

    this.state = {

      stateValue:true    }

  }//2.如有改变设定值this.setState({

    stateValue: false})//3.在父组件中传值

    const huoquValue = this.props.stateValue;

    if ( !this.props.stateValue ) {

        console.log('stateValue', this,.props.stateValue)

    }

}

值得注意一点的是,setState 是一个异步方法,需要render值行的时候才会触发。可以参考博客【 React的setState立即执行方案】。

(二)父组件将方法传给子组件,子组件通过props来获取。

//父组件文件中:

    classTestHtmlextendsReact.Component{

    //1.方法的声明

    propsFunction() {

        console.log('声明在父组件的方法')

    }

    render() {

        return (

            //2.传递           

        )

    }

}functionmapStateToProps(state, ownProps){    return {

    }

}functionmapDispatchToProps(dispatch){    return {

        ...bindActionCreators(action, dispatch)

    }

}

export default connect(mapStateToProps, mapDispatchToProps)(TestHtml)

//子组件中获取

<Button onClick={this.props.propsFunction} />

说明:写这一段的时候,突发奇想,竟然就把react-redux的页面结构的写出来了。好吧,等下写完这篇,如果有必要就具体写一下这个页面的结构类型吧。

(三)在父组件中调用子组件中的方法,通过ref和refs实现。

//这里就简要说明一下

//思路是给子组件一个ref,然后父组件通过refs获取

componentWillReceiveProps(nextProps) {

    this.refs.jiedian.子组件的方法名()

    //举个例子

    // this.refs.getSwordButton.setFieldsValue({

    //  xmlUrl: nextProps.sysCode==null ? nextProps.accountInfo.xmlUrl : nextProps.sysCode    // })

}

(四)特殊情况 

当你发现这些方法都不起作用的时候,或者说,因为某些限制而不能用的时候,你就换一下思路了。 

其实我们还可以通过action–reduce的方式在他们的外部且是公共的action-reduce中搞定。 

其中涉及到方法我们就直接新建一个方法,在action中声明,在reduce中实现。如果只是某个值,用不到函数的,我们可以直接在reduce里面设定,且赋值,最后通过mapStateToProps获取。 

关于mapStateToProps,可以直接参考【React依赖注入说明(mapStateToProps/mapDispatchToProps)

总结 

1.父组件通过state向子组件传值,子组件通过props获取父组件所传的值。 

2.子组件通过prop获取父组件中定义的函数方法,但是需要在父组件调用子组件的标签中写明。 

3.父组件通过refs调用子组件中声明的方法,但是需要给子组件添加一个ref节点 

4.组件之间的交流也不一定要沉在这些直接性的关联的东西,我们的思维还可以提神一个高度,可以在action-reduce中搞定。 

三. 兄弟组件之间传值


兄弟组件的意思就是指没有任何嵌套关系的组件之间传值. 这种需求也是非常常见的,

如果组件之间没有任何关系,组件嵌套层次比较深(个人认为 2 层以上已经算深了),或者你为了一些组件能够订阅、写入一些信号,不想让组件之间插入一个组件,让两个组件处于独立的关系。对于事件系统,这里有 2 个基本操作步骤:订阅(subscribe)/监听(listen)一个事件通知,并发送(send)/触发(trigger)/发布(publish)/发送(dispatch)一个事件通知那些想要的组件。

下面讲介绍 3 种模式来处理事件,你能点击这里来比较一下它们。

简单总结一下:

(1) Event Emitter/Target/Dispatcher

特点:需要一个指定的订阅源

// to subscribe

otherObject.addEventListener(‘click’,function(){ alert(‘click!’); });

// to dispatch

this.dispatchEvent(‘click’);

(2) Publish / Subscribe

特点:触发事件的时候,你不需要指定一个特定的源,因为它是使用一个全局对象来处理事件(其实就是一个全局

广播的方式来处理事件)

// to subscribe

globalBroadcaster.subscribe(‘click’,function(){ alert(‘click!’); });

// to dispatch

globalBroadcaster.publish(‘click’);

(3) Signals

特点:与Event Emitter/Target/Dispatcher相似,但是你不要使用随机的字符串作为事件触发的引用。触发事件的每一个对象都需要一个确切的名字(就是类似硬编码类的去写事件名字),并且在触发的时候,也必须要指定确切的事件。(看例子吧,很好理解)

// to subscribe

otherObject.clicked.add(function(){ alert(‘click’); });

// to dispatch

this.clicked.dispatch();

如果你只想简单的使用一下,并不需要其他操作,可以用简单的方式来实现:

// 简单实现了一下 subscribe 和 dispatch

varEventEmitter = {

    _events: {},

dispatch: function (event,data) {

if(!this._events[event]) {// 没有监听事件

return;

        }

for(vari =0; i

this._events[event][i](data);

        }

    },

    subscribe: function (event, callback) {

// 创建一个新事件数组

if(!this._events[event]) {

this._events[event] = [];

      }

this._events[event].push(callback);

    }

};

otherObject.subscribe('namechanged', function(data) { alert(data.name); });

this.dispatch('namechanged', { name:'John'});

如果你想使用 Publish/Subscribe 模型,可以使用:PubSubJS

React 团队使用的是:js-signals它基于 Signals 模式,用起来相当不错。

Events in React

使用 React 事件的时候,必须关注下面两个方法:

componentDidMount

componentWillUnmount

在处理事件的时候,需要注意:

在 componentDidMount 事件中,如果组件挂载(mounted)完成,再订阅事件;当组件卸载(unmounted)的时候,在 componentWillUnmount 事件中取消事件的订阅。

(如果不是很清楚可以查阅 React 对生命周期介绍的文档,里面也有描述。原文中介绍的是 componentWillMount 个人认为应该是挂载完成后订阅事件,比如Animation这个就必须挂载,并且不能动态的添加,谨慎点更好)

因为组件的渲染和销毁是由 React 来控制的,我们不知道怎么引用他们,所以EventEmitter 模式在处理组件的时候用处不大。

pub/sub 模式可以使用,你不需要知道引用。

下面来一个例子:实现有多个 product 组件,点击他们的时候,展示 product 的名字。

(我在例子中引入了之前推荐的 PubSubJS 库,如果你觉得引入代价太大,也可以手写一个简版,还是比较容易的,很好用哈,大家也可以体验,但是我还是不推荐全局广播的方式)

// 定义一个容器

varProductList = React.createClass({

render:function(){

return(

    <div>

            <ProductSelection />

            <Product name="product 1" />

            <Product name="product 2"/>

            <Product name="product 3" />

    </div>

      );

    }

});

// 用于展示点击的产品信息容器

varProductSelection = React.createClass({

getInitialState:function(){

return{

selection:'none'

    };

  },

componentDidMount:function(){

this.pubsub_token = PubSub.subscribe('products',function(topic, product){

      this.setState({

        selection: product

      });

    }.bind(this));

  },

componentWillUnmount:function(){

    PubSub.unsubscribe(this.pubsub_token);

  },

render:function(){

return(


You have selected the product : {this.state.selection}

    );

  }

});

varProduct = React.createClass({

onclick:function(){

PubSub.publish('products', this.props.name);

  },

render:function(){

return

{this.props.name}

;

  }

});

ES6: yield and js-csp

ES6 中有一种传递信息的方式,使用生成函数(generators)和 yield 关键字。可以看一下https://github.com/ubolonton/js-csp

(这里我写一个简单的 DEMO 介绍一下这种新的传递方式,其实大同小异)

function*list(){

for(vari =0; i

yieldarguments[i];

    }

return"done.";

}

varo = list(1,2,3);

varcur = o.next;

while(!cur.done) {

    cur = o.next();

console.log(cur);

}

以上例子来自于屈屈的一篇博客:ES6 中的生成器函数介绍  屈屈是一个大牛,大家可以关注他的博客。

通常来说,你有一个队列,对象在里面都能找到一个引用,在定义的时候锁住,当发生的时候,立即打开锁执行。js-csp 是一种解决办法,也许以后还会有其他解决办法。

结尾

在实际应用中,按照实际要解决的需求选择解决办法。对于小应用程序,你可以使用 props 和回调的方法进行组件之间的数据交换。你可以通过 pub/sub 模式,以避免污染你的组件。在这里,我们不是在谈论数据,只是组件。对于数据的请求、数据的变化等场景,可以使用 Facebook 的 Flux、Relay、GraphQL 来处理,都非常的好用。

文中的每一个例子我都验证过了,主要使用最原始的引入文件方式,创建服务使用的 http-server 包,大家也可以尝试自己来一次。



参考文档:    1. https://blog.csdn.net/limm33/article/details/50942863

2.https://www.jianshu.com/p/8b845f05cf4b

3.https://blog.csdn.net/genius_yym/article/details/73057248

4. https://segmentfault.com/q/1010000007295553?_ea=1300560

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容