React 组件通讯

React 组件 之间的通信

在这里插入图片描述

合理的创建标题,有助于目录的生成

组件之间正常的传递是由父向子的正常传递!
1.父组件通过属性进行传递,子组件通过props获取
2.通过回调进行传递数据
3.兄弟组件之间的传值:
a.通过相同的父组件进行传递数据–子组件A通过回调函数形式将数据传给父组件,接着父组件通过属性将数据传递给子组件B
b.通过发布/订阅进行传递 – 在子组件A中 commentDidMount函数中,发布事件,在子组件B中commentDidMount函数中对事件进行监听
c.使用context进行传递

		class Parent extends Component(
			   constructor(props) {
			        super(props);
			        this.state = { value: '' }
			    }   
			   getChildContext(){
			        return {
			          this.value = this.state.value;
			        }  
			    }
	
	  render() {
	        return (
	            <div>
	                    <Child1 />
	                    <Child2 />
	            </div>
	        )
	    }
	}
	
	class Child1 extends Component{
	    change:function(){
	        this.context.value = "heiheihei"
	    }
	    render() {
	        return (
	            <div>
	                子组件一
	                <p>{this.context.value}</p>
	            </div>
	        )
	    }
	}
	
	class Child2 extends Component{
	    render() {
	        return (
	            <div>
	                子组件二
	                <p>{this.context.value}</p>
	            </div>
	        )
	    }
	}

context局限性

  1. context在react中只是实验阶段未来可能改变
  2. 若shouldComponentUpdate中return false会影响context的传值,使子组件无法更新
  3. 组件发purComponent也会影响context的传值,影响子组件的更新

4.没有任何嵌套关系的组件之间传值
如果组件之间没有任何关系,组件嵌套层次比较深(个人认为 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
var EventEmitter = {
_events: {},
dispatch: function (event, data) {
if (!this._events[event]) { // 没有监听事件
return;
}
for (var i = 0; i < this._events[event].length; i++) {
this._events[event]i;
}
},
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’ });

Events in React

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

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

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

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

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

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

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

// 定义一个容器

var ProductList = React.createClass({
    render: function () {
      return (
        <div>
          <ProductSelection />
          <Product name="product 1" />
          <Product name="product 2" />
          <Product name="product 3" />
        </div>
      );
    }
});

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

	var ProductSelection = 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 (
	      <p>You have selected the product : {this.state.selection}</p>
	    );
	  }
	});

var Product = React.createClass({
  onclick: function () {
    PubSub.publish('products', this.props.name);
  },
  render: function() {
    return <div onClick={this.onclick}>{this.props.name}</div>;
  }
});

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

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

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);
}

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

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

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

引用: https://blog.youkuaiyun.com/limm33/article/details/50942863

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值