【问题标题】:EventEmitter and Subscriber ES6 Syntax with React Native带有 React Native 的 EventEmitter 和 Subscriber ES6 语法
【发布时间】:2016-08-14 22:42:42
【问题描述】:

我正在尝试在反应原生类中的两个组件之间实现 EventEmitter/Subscriber 关系。我看过参考了以下材料:

这些解决方案足以满足我想要完成的任务,但是,它们需要在接收组件上使用 mixins: [Subscribable.Mixin] 才能与 Subscriber 正常工作。不幸的是,我正在使用 ES6 并从 Component 扩展我的类,所以我不能使用这种混合语法。

我的问题是:如何在不使用 mixins 的情况下在 ES6 中实现上述解决方案?

【问题讨论】:

  • 这里有人建议简单地使用编写组件的“旧方式”:hi-tips.tumblr.com/post/137014836571/… 我有同样的问题,想知道在 ES6 中是否有任何正确的方法
  • 我还在寻找这个。我不愿意开始使用react-mixin

标签: react-native mixins eventemitter


【解决方案1】:

你不需要 mixins 来使用 EventEmitters。

简单演示:

import EventEmitter from 'EventEmitter';

let x = new EventEmitter();

function handler(arg) {
    console.log(`event-name has occurred! here is the event data arg=${JSON.stringify(arg)}`);
}

x.addListener('event-name', handler);

x.emit('event-name', { es6rules: true, mixinsAreLame: true });

addListener 的完整签名需要三个参数:

EventEmitter.addListener(eventName, handler, handlerContext)

在 react 组件中,您可能希望使用该上下文 arg,以便处理程序可以是类方法而不是内联函数,并且仍然保留 this == component instance。例如:

componentDidMount() {
    someEmitter.addListener('awesome', this.handleAwesomeEvents, this);
    // the generalist suggests the alternative:
    someEmitter.addListener('awesome', this.handleAwesomeEvents.bind(this));
}

handleAwesomeEvents = (event) => {
    let awesomeness = event.awesomeRating;

    // if you don't provide context in didMount,
    // "this" will not refer to the component,
    // and this next line will throw
    this.setState({ awesomeness });
};

仅供参考:我通过查看the infamous Subscribable mixin 的绝对不神奇的实现得到了这个。 Google 搜索结果基本上是 Ramsay 的基于 mixin 的单个演示的回音室。

附:至于将此发射器暴露给另一个组件,我可能会让拥有的组件提供一个接收发射器引用的函数,然后创建发射器的组件将有条件地使用发射器执行该道具。

// owner's render method:
<ThingThatEmits
    onEmitterReady={(emitter) => this.thingEmitter = emitter}
/>

// inside ThingThatEmits:
componentDidMount() {
    this.emitter = new EventEmitter();

    if(typeof this.props.onEmitterReady === 'function') {
        this.props.onEmitterReady(this.emitter);
    }
}

【讨论】:

  • 谢谢!您的“简单演示”正是我需要看到它才能点击的内容。
  • 嗨,汤姆,当我尝试拨打 let test = new EventEmitter(); 时,它会抛出 undefined is not a constructor (evaluating 'new _reactNative.EventEmitter()') 对此有什么想法吗?
  • @Richard:没有。你使用的是什么版本的 react-native?你确定你导入正确吗?您是否尝试过重新启动您的 RN 打包程序?这是构建时失败还是运行时失败?
  • 我知道这是相当晚的响应,但你应该像这样import EventEmitter from "EventEmitter";而不是这样import { EventEmitter } from "EventEmitter";进行导入
  • 您在最后一个代码 sn-p 中所做的与通过 props 从父级向其子级提供函数有何不同?
【解决方案2】:

这可能是一个很晚的答案,但我只是将其发布给任何可能觉得这很有用的人。

截至撰写本答案时(2020 年 7 月),React Native 与 0.60.0+ 版本相比发生了很大变化,您可以使用 EventEmitter 的实例,也可以静态调用 DeviceEventEmitter 方法。


这里是一个使用EventEmitter的例子:


import { EventEmitter } from 'events';

const newEvent = new EventEmitter();

// then you can use: "emit", "on", "once", and "off"
newEvent.on('example.event', () => {
  // ...
});


另一个使用DeviceEventEmitter的例子:


import { DeviceEventEmitter } from 'react-native';

// then you can directly use: "emit", "addListener", and "removeAllListeners"
DeviceEventEmitter.emit('example.event', ['foo', 'bar', 'baz']);

希望对仍在寻找在 React Native 中实现自定义事件的方法的任何人都派上用场。

【讨论】:

  • 我喜欢这个 DeviceEventEmitter 我不需要创建一个新实例。谢谢!
  • DeviceEventEmitter 对我来说工作得很好,但仍然很好奇为什么我找不到它的 react-native 文档
【解决方案3】:

我能够通过react-mixin 获得解决方法。不确定它有多合适,但它无需任何修改即可工作。关键是在类定义之后添加reactMixin(DetailView.prototype, Subscribable.Mixin);

离开为 EventEmitter 和 Subscribable 浮动的示例:

'use strict';

var reactMixin = require('react-mixin');
var React = require('react-native');
var EventEmitter = require('EventEmitter');
var Subscribable = require('Subscribable');

var {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    NavigatorIOS
} = React;

class MainView extends Component {
    constructor(props){
      super(props);
      this.EventEmitter = new EventEmitter();
    }

    somethingHappenedFunction(){
      this.EventEmitter.emit("update_event", { message: "hello from up here"});
    }

    //rest of the class
}

class DetailView extends Component {
   componentDidMount(){
     this.addListenerOn(this.props.events, 'update_event', this.miscFunction);
   }

   miscFunction(args) {
    console.log("message: %s", args.message);
   }

   //rest of the class
}
reactMixin(DetailView.prototype, Subscribable.Mixin);

【讨论】:

    猜你喜欢
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 2017-05-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多