使用 React Native 的 EventEmitter 和 Subscriber ES6 语法
EventEmitter and Subscriber ES6 Syntax with React Native
我正在尝试在 React Native class 中实现两个组件之间的 EventEmitter/Subscriber 关系。我看到参考了以下资料:
这些解决方案足以满足我要完成的任务,但是,它们需要在接收组件上使用 mixins: [Subscribable.Mixin]
才能与 Subscriber
一起正常工作。不幸的是,我正在使用 ES6 并从 Component
扩展我的 classes,所以我不能使用这种混合语法。
我的问题是:如何在不使用 mixin 的情况下在 ES6 中实现上述解决方案?
我能够通过 react-mixin 获得解决方法。不确定它有多合适,但它无需任何修改即可工作。关键是在 class 定义之后添加 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);
您不需要 mixin 即可使用 EventEmitter。
简单演示:
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 组件中,您可能希望使用该上下文参数,以便处理程序可以是 class 方法而不是内联函数,并且仍然保留 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 的单一演示的回音室。
P.S。至于将这个发射器暴露给另一个组件,我可能会让拥有的组件提供一个函数来接收发射器引用,然后创建发射器的组件将有条件地使用发射器执行该道具。
// 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);
}
}
这可能是一个很晚的答案,但我会把它放在那里,以供可能觉得它有用的任何人使用。
截至撰写此答案时(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 中实现自定义事件的方法的任何人都派上用场。
我正在尝试在 React Native class 中实现两个组件之间的 EventEmitter/Subscriber 关系。我看到参考了以下资料:
这些解决方案足以满足我要完成的任务,但是,它们需要在接收组件上使用 mixins: [Subscribable.Mixin]
才能与 Subscriber
一起正常工作。不幸的是,我正在使用 ES6 并从 Component
扩展我的 classes,所以我不能使用这种混合语法。
我的问题是:如何在不使用 mixin 的情况下在 ES6 中实现上述解决方案?
我能够通过 react-mixin 获得解决方法。不确定它有多合适,但它无需任何修改即可工作。关键是在 class 定义之后添加 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);
您不需要 mixin 即可使用 EventEmitter。
简单演示:
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 组件中,您可能希望使用该上下文参数,以便处理程序可以是 class 方法而不是内联函数,并且仍然保留 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 的单一演示的回音室。
P.S。至于将这个发射器暴露给另一个组件,我可能会让拥有的组件提供一个函数来接收发射器引用,然后创建发射器的组件将有条件地使用发射器执行该道具。
// 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);
}
}
这可能是一个很晚的答案,但我会把它放在那里,以供可能觉得它有用的任何人使用。
截至撰写此答案时(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 中实现自定义事件的方法的任何人都派上用场。