react-native中事件监听时使用插件DeviceEventEmitter这个来进行实现,在这里我们进行讲解一下基本语法,如下所示
在想要接受监听的地方进行添加监听,假如是one.js页面
import { DeviceEventEmitter } from 'react-native';
...
componentDidMount() {//收到监听this.listener = DeviceEventEmitter.addListener('通知名称', (message) => {//收到监听后想做的事情console.log(message); //监听})
}
componentWillUnmount() {//移除监听if (this.listener) {this.listener.remove();}}
...
从上面代码中,我们能够看到通过DeviceEventEmitter进行设置了监听,根据React-Native生命周期,当组件加载的时候,我们进行监听,当组件卸载的时候,我们移除监听事件
在我们需要触发one.js页面的监听的时候,我们能够在其他页面进行处罚,假定触发页面为two.js,则代码如下所示:
import { DeviceEventEmitter } from 'react-native';
...
startEmit() {//准备值,发监听const message = '监听';DeviceEventEmitter.emit('通知名称', message);
}
...
在这里我们使用两个页面进行验证全局监听事件,在这里我们使用"react-navigation"(“1.5.12”),跳转界面,首先我们去实现第一个界面,在这个界面用于设置监听,代码如下所示:
import React, { Component } from 'react';
import { Button, Text, View, DeviceEventEmitter } from &#39;react-native&#39;;class One extends Component {constructor(props) {super(props);this.state &#61; { result: &#39;我是默认值&#39; };}componentDidMount() {// 收到监听this.listener &#61; DeviceEventEmitter.addListener(&#39;changeResult&#39;, (message) &#61;> {// 收到监听后想做的事情 // 监听this.setState({ result: message });});}componentWillUnmount() {// 移除监听if (this.listener) { this.listener.remove(); }}_onChange &#61; () &#61;> {const { navigation } &#61; this.props;navigation.navigate(&#39;Two&#39;);};render() {return (<View style&#61;{{ flex: 1, justifyContent: &#39;center&#39;, alignItems: &#39;center&#39; }}><Button onPress&#61;{this._onChange} title&#61;"跳转到第二个页面" /><Text style&#61;{{ fontSize: 20, marginTop: 30 }}>{this.state.result}</Text></View>);}
}
export default One;
之后我们完成第二个界面&#xff0c;在这个界面&#xff0c;我们进行对第一个界面监听事件的触发&#xff0c;代码如下所示&#xff1a;
import React, { Component } from &#39;react&#39;;
import { Button, View, DeviceEventEmitter } from &#39;react-native&#39;;
class Two extends Component {startEmit &#61; () &#61;> {// 准备值&#xff0c;发监听const message &#61; &#39;监听发出通过&#xff0c;让one页面的值进行改变&#39;;DeviceEventEmitter.emit(&#39;changeResult&#39;, message);};render() {return (<View style&#61;{{ flex: 1, justifyContent: &#39;center&#39;, alignItems: &#39;center&#39; }}><Button onPress&#61;{this.startEmit} title&#61;"触发第一个页面的监听事件" /></View>);}
}
export default Two;
现在我们来看看具体的显示效果&#xff1a;
既然基本用法我们能够使用了&#xff0c;那么我们就找找看能不能看到源码信息&#xff0c;我们通过在one.js页面中点击(command&#43;左键) DeviceEventEmitter
插件&#xff0c;我们能够看到如下界面代码&#xff1a;
在 // Plugins处我们能够看到这一行代码 get DeviceEventEmitter() { return require(&#39;RCTDeviceEventEmitter&#39;); },
也就是说我们 DeviceEventEmitter
在底层实现是RCTDeviceEventEmitter&#xff0c;那么我们就可以更加深入的查看下去&#xff0c;我们能够在Libaray文件夹中看到如下界面&#xff1a;
/*** Deprecated - subclass NativeEventEmitter to create granular event modules instead of* adding all event listeners directly to RCTDeviceEventEmitter.*/
class RCTDeviceEventEmitter extends EventEmitter {sharedSubscriber: EventSubscriptionVendor;constructor() {const sharedSubscriber &#61; new EventSubscriptionVendor();super(sharedSubscriber);this.sharedSubscriber &#61; sharedSubscriber;}addListener(eventType: string, listener: Function, context: ?Object): EmitterSubscription {if (__DEV__) {checkNativeEventModule(eventType);}return super.addListener(eventType, listener, context);}removeAllListeners(eventType: ?string) {if (__DEV__) {checkNativeEventModule(eventType);}super.removeAllListeners(eventType);}removeSubscription(subscription: EmitterSubscription) {if (subscription.emitter !&#61;&#61; this) {subscription.emitter.removeSubscription(subscription);} else {super.removeSubscription(subscription);}}
}module.exports &#61; new RCTDeviceEventEmitter();
从代码中&#xff0c;我们能够看出实现了的方法有addListener,但是没有我们在使用中的其他方法&#xff0c;我们对代码进行分析&#xff0c;可以看到&#xff0c;在这里进行引入了下面这两个文件
const EventEmitter &#61; require(&#39;EventEmitter&#39;);
const EventSubscriptionVendor &#61; require(&#39;EventSubscriptionVendor&#39;);
于是我们能够看到如下界面&#xff1a;
能够看到我们需要的文件&#xff0c;打开EventEmitter.js文件&#xff0c;能够看到其实现代码了&#xff0c;内容如下所示&#xff1a;
/*** Copyright (c) 2015-present, Facebook, Inc.** This source code is licensed under the MIT license found in the* LICENSE file in the root directory of this source tree.** &#64;providesModule EventEmitter* &#64;noflow* &#64;typecheck*/
&#39;use strict&#39;;const EmitterSubscription &#61; require(&#39;EmitterSubscription&#39;);
const EventSubscriptionVendor &#61; require(&#39;EventSubscriptionVendor&#39;);const emptyFunction &#61; require(&#39;fbjs/lib/emptyFunction&#39;);
const invariant &#61; require(&#39;fbjs/lib/invariant&#39;);/*** &#64;class EventEmitter* &#64;description* An EventEmitter is responsible for managing a set of listeners and publishing* events to them when it is told that such events happened. In addition to the* data for the given event it also sends a event control object which allows* the listeners/handlers to prevent the default behavior of the given event.** The emitter is designed to be generic enough to support all the different* contexts in which one might want to emit events. It is a simple multicast* mechanism on top of which extra functionality can be composed. For example, a* more advanced emitter may use an EventHolder and EventFactory.*/
class EventEmitter {_subscriber: EventSubscriptionVendor;_currentSubscription: ?EmitterSubscription;/*** &#64;constructor** &#64;param {EventSubscriptionVendor} subscriber - Optional subscriber instance* to use. If omitted, a new subscriber will be created for the emitter.*/constructor(subscriber: ?EventSubscriptionVendor) {this._subscriber &#61; subscriber || new EventSubscriptionVendor();}/*** Adds a listener to be invoked when events of the specified type are* emitted. An optional calling context may be provided. The data arguments* emitted will be passed to the listener function.** TODO: Annotate the listener arg&#39;s type. This is tricky because listeners* can be invoked with varargs.** &#64;param {string} eventType - Name of the event to listen to* &#64;param {function} listener - Function to invoke when the specified event is* emitted* &#64;param {*} context - Optional context object to use when invoking the* listener*/addListener(eventType: string, listener: Function, context: ?Object): EmitterSubscription {return (this._subscriber.addSubscription(eventType,new EmitterSubscription(this, this._subscriber, listener, context)) : any);}/*** Similar to addListener, except that the listener is removed after it is* invoked once.** &#64;param {string} eventType - Name of the event to listen to* &#64;param {function} listener - Function to invoke only once when the* specified event is emitted* &#64;param {*} context - Optional context object to use when invoking the* listener*/once(eventType: string, listener: Function, context: ?Object): EmitterSubscription {return this.addListener(eventType, (...args) &#61;> {this.removeCurrentListener();listener.apply(context, args);});}/*** Removes all of the registered listeners, including those registered as* listener maps.** &#64;param {?string} eventType - Optional name of the event whose registered* listeners to remove*/removeAllListeners(eventType: ?string) {this._subscriber.removeAllSubscriptions(eventType);}/*** Provides an API that can be called during an eventing cycle to remove the* last listener that was invoked. This allows a developer to provide an event* object that can remove the listener (or listener map) during the* invocation.** If it is called when not inside of an emitting cycle it will throw.** &#64;throws {Error} When called not during an eventing cycle** &#64;example* var subscription &#61; emitter.addListenerMap({* someEvent: function(data, event) {* console.log(data);* emitter.removeCurrentListener();* }* });** emitter.emit(&#39;someEvent&#39;, &#39;abc&#39;); // logs &#39;abc&#39;* emitter.emit(&#39;someEvent&#39;, &#39;def&#39;); // does not log anything*/removeCurrentListener() {invariant(!!this._currentSubscription,&#39;Not in an emitting cycle; there is no current subscription&#39;);this.removeSubscription(this._currentSubscription);}/*** Removes a specific subscription. Called by the &#96;remove()&#96; method of the* subscription itself to ensure any necessary cleanup is performed.*/removeSubscription(subscription: EmitterSubscription) {invariant(subscription.emitter &#61;&#61;&#61; this,&#39;Subscription does not belong to this emitter.&#39;);this._subscriber.removeSubscription(subscription);}/*** Returns an array of listeners that are currently registered for the given* event.** &#64;param {string} eventType - Name of the event to query* &#64;returns {array}*/listeners(eventType: string): [EmitterSubscription] {const subscriptions: ?[EmitterSubscription] &#61; (this._subscriber.getSubscriptionsForType(eventType): any);return subscriptions? subscriptions.filter(emptyFunction.thatReturnsTrue).map(function(subscription) {return subscription.listener;}): [];}/*** Emits an event of the given type with the given data. All handlers of that* particular type will be notified.** &#64;param {string} eventType - Name of the event to emit* &#64;param {...*} Arbitrary arguments to be passed to each registered listener** &#64;example* emitter.addListener(&#39;someEvent&#39;, function(message) {* console.log(message);* });** emitter.emit(&#39;someEvent&#39;, &#39;abc&#39;); // logs &#39;abc&#39;*/emit(eventType: string) {const subscriptions: ?[EmitterSubscription] &#61; (this._subscriber.getSubscriptionsForType(eventType): any);if (subscriptions) {for (let i &#61; 0, l &#61; subscriptions.length; i < l; i&#43;&#43;) {const subscription &#61; subscriptions[i];// The subscription may have been removed during this event loop.if (subscription) {this._currentSubscription &#61; subscription;subscription.listener.apply(subscription.context,Array.prototype.slice.call(arguments, 1));}}this._currentSubscription &#61; null;}}/*** Removes the given listener for event of specific type.** &#64;param {string} eventType - Name of the event to emit* &#64;param {function} listener - Function to invoke when the specified event is* emitted** &#64;example* emitter.removeListener(&#39;someEvent&#39;, function(message) {* console.log(message);* }); // removes the listener if already registered**/removeListener(eventType: String, listener) {const subscriptions: ?[EmitterSubscription] &#61; (this._subscriber.getSubscriptionsForType(eventType): any);if (subscriptions) {for (let i &#61; 0, l &#61; subscriptions.length; i < l; i&#43;&#43;) {const subscription &#61; subscriptions[i];// The subscription may have been removed during this event loop.// its listener matches the listener in method parametersif (subscription && subscription.listener &#61;&#61;&#61; listener) {subscription.remove();}}}}
}module.exports &#61; EventEmitter;
上述代码中&#xff0c;我们能够找到我们在one.js和two.js中使用的方法&#xff0c;如addListener通过传递字符串类型的事件类型&#xff0c;监听使用的方法和上下文进行添加订阅&#xff0c;如下所示&#xff1a;
addListener(eventType: string, listener: Function, context: ?Object): EmitterSubscription {return (this._subscriber.addSubscription(eventType,new EmitterSubscription(this, this._subscriber, listener, context)) : any);}
还有emit方法&#xff0c;通过事件类型&#xff0c;遍历所有的订阅事件进行获取指定eventType的subscriptions详细信息&#xff0c;然后通过apply方法将参数传递给上下文&#xff0c;如下所示代码&#xff1a;
emit(eventType: string) {const subscriptions: ?[EmitterSubscription] &#61; (this._subscriber.getSubscriptionsForType(eventType): any);if (subscriptions) {for (let i &#61; 0, l &#61; subscriptions.length; i < l; i&#43;&#43;) {const subscription &#61; subscriptions[i];// The subscription may have been removed during this event loop.if (subscription) {this._currentSubscription &#61; subscription;subscription.listener.apply(subscription.context,Array.prototype.slice.call(arguments, 1));}}this._currentSubscription &#61; null;}}
也就是我们发起请求时message信息的处理方式&#xff0c;在这过程中&#xff0c;当然还有其他几处代码进行了事件处理&#xff0c;在这里就不一一说明了
以上就是DeviceEventEmitter的使用