赞
踩
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 'react-native';
class One extends Component {
constructor(props) {
super(props);
this.state = { result: '我是默认值' };
}
componentDidMount() {
// 收到监听
this.listener = DeviceEventEmitter.addListener('changeResult', (message) => {
// 收到监听后想做的事情 // 监听
this.setState({ result: message });
});
}
componentWillUnmount() {
// 移除监听
if (this.listener) { this.listener.remove(); }
}
_onChange = () => {
const { navigation } = this.props;
navigation.navigate('Two');
};
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button onPress={this._onChange} title="跳转到第二个页面" />
<Text style={{ fontSize: 20, marginTop: 30 }}>{this.state.result}</Text>
</View>
);
}
}
export default One;
之后我们完成第二个界面,在这个界面,我们进行对第一个界面监听事件的触发,代码如下所示:
import React, { Component } from 'react';
import { Button, View, DeviceEventEmitter } from 'react-native';
class Two extends Component {
startEmit = () => {
// 准备值,发监听
const message = '监听发出通过,让one页面的值进行改变';
DeviceEventEmitter.emit('changeResult', message);
};
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Button onPress={this.startEmit} title="触发第一个页面的监听事件" />
</View>
);
}
}
export default Two;
现在我们来看看具体的显示效果:
既然基本用法我们能够使用了,那么我们就找找看能不能看到源码信息,我们通过在one.js页面中点击(command+左键) DeviceEventEmitter
插件,我们能够看到如下界面代码:
在 // Plugins处我们能够看到这一行代码 get DeviceEventEmitter() { return require('RCTDeviceEventEmitter'); },
也就是说我们 DeviceEventEmitter
在底层实现是RCTDeviceEventEmitter,那么我们就可以更加深入的查看下去,我们能够在Libaray文件夹中看到如下界面:
/**
* 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 = new EventSubscriptionVendor();
super(sharedSubscriber);
this.sharedSubscriber = 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 !== this) {
subscription.emitter.removeSubscription(subscription);
} else {
super.removeSubscription(subscription);
}
}
}
module.exports = new RCTDeviceEventEmitter();
从代码中,我们能够看出实现了的方法有addListener,但是没有我们在使用中的其他方法,我们对代码进行分析,可以看到,在这里进行引入了下面这两个文件
const EventEmitter = require('EventEmitter');
const EventSubscriptionVendor = require('EventSubscriptionVendor');
于是我们能够看到如下界面:
能够看到我们需要的文件,打开EventEmitter.js文件,能够看到其实现代码了,内容如下所示:
/**
* 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.
*
* @providesModule EventEmitter
* @noflow
* @typecheck
*/
'use strict';
const EmitterSubscription = require('EmitterSubscription');
const EventSubscriptionVendor = require('EventSubscriptionVendor');
const emptyFunction = require('fbjs/lib/emptyFunction');
const invariant = require('fbjs/lib/invariant');
/**
* @class EventEmitter
* @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;
/**
* @constructor
*
* @param {EventSubscriptionVendor} subscriber - Optional subscriber instance
* to use. If omitted, a new subscriber will be created for the emitter.
*/
constructor(subscriber: ?EventSubscriptionVendor) {
this._subscriber = 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's type. This is tricky because listeners
* can be invoked with varargs.
*
* @param {string} eventType - Name of the event to listen to
* @param {function} listener - Function to invoke when the specified event is
* emitted
* @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.
*
* @param {string} eventType - Name of the event to listen to
* @param {function} listener - Function to invoke only once when the
* specified event is emitted
* @param {*} context - Optional context object to use when invoking the
* listener
*/
once(eventType: string, listener: Function, context: ?Object): EmitterSubscription {
return this.addListener(eventType, (...args) => {
this.removeCurrentListener();
listener.apply(context, args);
});
}
/**
* Removes all of the registered listeners, including those registered as
* listener maps.
*
* @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.
*
* @throws {Error} When called not during an eventing cycle
*
* @example
* var subscription = emitter.addListenerMap({
* someEvent: function(data, event) {
* console.log(data);
* emitter.removeCurrentListener();
* }
* });
*
* emitter.emit('someEvent', 'abc'); // logs 'abc'
* emitter.emit('someEvent', 'def'); // does not log anything
*/
removeCurrentListener() {
invariant(
!!this._currentSubscription,
'Not in an emitting cycle; there is no current subscription'
);
this.removeSubscription(this._currentSubscription);
}
/**
* Removes a specific subscription. Called by the `remove()` method of the
* subscription itself to ensure any necessary cleanup is performed.
*/
removeSubscription(subscription: EmitterSubscription) {
invariant(
subscription.emitter === this,
'Subscription does not belong to this emitter.'
);
this._subscriber.removeSubscription(subscription);
}
/**
* Returns an array of listeners that are currently registered for the given
* event.
*
* @param {string} eventType - Name of the event to query
* @returns {array}
*/
listeners(eventType: string): [EmitterSubscription] {
const subscriptions: ?[EmitterSubscription] = (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.
*
* @param {string} eventType - Name of the event to emit
* @param {...*} Arbitrary arguments to be passed to each registered listener
*
* @example
* emitter.addListener('someEvent', function(message) {
* console.log(message);
* });
*
* emitter.emit('someEvent', 'abc'); // logs 'abc'
*/
emit(eventType: string) {
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any);
if (subscriptions) {
for (let i = 0, l = subscriptions.length; i < l; i++) {
const subscription = subscriptions[i];
// The subscription may have been removed during this event loop.
if (subscription) {
this._currentSubscription = subscription;
subscription.listener.apply(
subscription.context,
Array.prototype.slice.call(arguments, 1)
);
}
}
this._currentSubscription = null;
}
}
/**
* Removes the given listener for event of specific type.
*
* @param {string} eventType - Name of the event to emit
* @param {function} listener - Function to invoke when the specified event is
* emitted
*
* @example
* emitter.removeListener('someEvent', function(message) {
* console.log(message);
* }); // removes the listener if already registered
*
*/
removeListener(eventType: String, listener) {
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any);
if (subscriptions) {
for (let i = 0, l = subscriptions.length; i < l; i++) {
const subscription = subscriptions[i];
// The subscription may have been removed during this event loop.
// its listener matches the listener in method parameters
if (subscription && subscription.listener === listener) {
subscription.remove();
}
}
}
}
}
module.exports = EventEmitter;
上述代码中,我们能够找到我们在one.js和two.js中使用的方法,如addListener通过传递字符串类型的事件类型,监听使用的方法和上下文进行添加订阅,如下所示:
addListener(
eventType: string, listener: Function, context: ?Object): EmitterSubscription {
return (this._subscriber.addSubscription(
eventType,
new EmitterSubscription(this, this._subscriber, listener, context)
) : any);
}
还有emit方法,通过事件类型,遍历所有的订阅事件进行获取指定eventType的subscriptions详细信息,然后通过apply方法将参数传递给上下文,如下所示代码:
emit(eventType: string) {
const subscriptions: ?[EmitterSubscription] = (this._subscriber.getSubscriptionsForType(eventType): any);
if (subscriptions) {
for (let i = 0, l = subscriptions.length; i < l; i++) {
const subscription = subscriptions[i];
// The subscription may have been removed during this event loop.
if (subscription) {
this._currentSubscription = subscription;
subscription.listener.apply(
subscription.context,
Array.prototype.slice.call(arguments, 1)
);
}
}
this._currentSubscription = null;
}
}
也就是我们发起请求时message信息的处理方式,在这过程中,当然还有其他几处代码进行了事件处理,在这里就不一一说明了
以上就是DeviceEventEmitter的使用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。