当前位置:   article > 正文

React-Native中事件监听DeviceEventEmitter

deviceeventemitter
基本语法

react-native中事件监听时使用插件DeviceEventEmitter这个来进行实现,在这里我们进行讲解一下基本语法,如下所示

1.设置监听

在想要接受监听的地方进行添加监听,假如是one.js页面

import { DeviceEventEmitter } from 'react-native';
...
componentDidMount() {
    //收到监听
    this.listener = DeviceEventEmitter.addListener('通知名称', (message) => {
    //收到监听后想做的事情
    console.log(message);  //监听
    })
}
componentWillUnmount() {
    //移除监听
    if (this.listener) {
      this.listener.remove();
    }
  }
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

从上面代码中,我们能够看到通过DeviceEventEmitter进行设置了监听,根据React-Native生命周期,当组件加载的时候,我们进行监听,当组件卸载的时候,我们移除监听事件

2.触发监听

在我们需要触发one.js页面的监听的时候,我们能够在其他页面进行处罚,假定触发页面为two.js,则代码如下所示:

import { DeviceEventEmitter } from 'react-native';
...
startEmit() {
    //准备值,发监听
    const message = '监听';
    DeviceEventEmitter.emit('通知名称', message);
}
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
实例操作

在这里我们使用两个页面进行验证全局监听事件,在这里我们使用"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;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

之后我们完成第二个界面,在这个界面,我们进行对第一个界面监听事件的触发,代码如下所示:

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;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

现在我们来看看具体的显示效果:

[emit]
源码说明

既然基本用法我们能够使用了,那么我们就找找看能不能看到源码信息,我们通过在one.js页面中点击(command+左键) DeviceEventEmitter插件,我们能够看到如下界面代码:

DeviceEventEmitter

在 // Plugins处我们能够看到这一行代码 get DeviceEventEmitter() { return require('RCTDeviceEventEmitter'); }, 也就是说我们 DeviceEventEmitter 在底层实现是RCTDeviceEventEmitter,那么我们就可以更加深入的查看下去,我们能够在Libaray文件夹中看到如下界面:

[emit]
之后找到 RCTDeviceEventEmitter.js 文件,如下代码,就是我从中复制的代码
/**
 * 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();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

从代码中,我们能够看出实现了的方法有addListener,但是没有我们在使用中的其他方法,我们对代码进行分析,可以看到,在这里进行引入了下面这两个文件

const EventEmitter = require('EventEmitter');
const EventSubscriptionVendor = require('EventSubscriptionVendor');
  • 1
  • 2

于是我们能够看到如下界面:

能够看到我们需要的文件,打开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;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219

上述代码中,我们能够找到我们在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);
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

还有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;
    }
  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

也就是我们发起请求时message信息的处理方式,在这过程中,当然还有其他几处代码进行了事件处理,在这里就不一一说明了


以上就是DeviceEventEmitter的使用

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/276635
推荐阅读
相关标签
  

闽ICP备14008679号