React VR组件与本机模块代码之间的持久桥接

时间:2017-06-06 15:46:48

标签: javascript react-native react-360

我试图让我的浏览器将一些DOM事件发送到React VR组件中。

我得到的最接近的是使用"原生模块的代码。"

(client.js)

export default class WindowEventsModule extends Module {
  constructor() {
    super('WindowEventsModule');

    this.listeners = {};

    window.onmousewheel = event => {
      this._emit('onmousewheel', event);
    };
  }

  init(rnctx) {
    this._rnctx = rnctx;
  }

  _emit(name, ob) {
    if (!this._rnctx) {
      return;
    }

    Object.keys(this.listeners).forEach(key => {
      this._rnctx.invokeCallback(this.listeners[key], [ob]);
    });
  }

  onMouseWheel(listener) {
    const key = String(Math.random());
    this.listeners[key] = listener;
    return () => {
      delete this.listeners[key];
    };
  }
}

(WindowEventsModule.js)

WindowEvents.onMouseWheel(function() {})

所以我的组件现在可以调用this._rnctx.callFunction(),并从DOM世界获得回调。

不幸的是,这仅适用一次。在呼叫后,RN显然会使我的回调无效。

我还研究了a = b + c + d + e; ,它可以调用一个名为" callable module"的东西上的任意函数。我不知道如何从那里到我的组件。

我有什么遗失的吗?将任意消息从本地世界提供给ReactVR后台工作程序的模式是什么?

1 个答案:

答案 0 :(得分:2)

我想通了......等等。

诀窍是创建我自己的" BatchedBridge"然后我可以使用上下文中的callFunction()来访问。

(index.vr.js)

import React from 'react';
import {AppRegistry, asset, Pano, View} from 'react-vr';
import BatchedBridge from 'react-native/Libraries/BatchedBridge/BatchedBridge';
import lodash from 'lodash';

class BrowserBridge {
    constructor() {
        this._subscribers = {};
    }

    subscribe(handler) {
        const key = String(Math.random());
        this._subscribers[key] = handler;
        return () => {
            delete this._subscribers[key];
        };
    }

    notifyEvent(name, event) {
        lodash.forEach(this._subscribers, handler => {
            handler(name, event);
        });
    }
}

const browserBridge = new BrowserBridge();
BatchedBridge.registerCallableModule(BrowserBridge.name, browserBridge);

export default class WelcomeToVR extends React.Component {
    constructor(props) {
        super(props);

        this.onBrowserEvent = this.onBrowserEvent.bind(this);
    }

    componentWillMount() {
        this.unsubscribe = browserBridge.subscribe(this.onBrowserEvent);
    }

    onBrowserEvent(name, event) {
        // Do the thing here
    }

    componentWillUnmount() {
        if (this.unsubscribe) {
            this.unsubscribe();
            delete this.unsubscribe;
        }
    }

    render() {
        //...
    }
};

AppRegistry.registerComponent('WelcomeToVR', () => WelcomeToVR);

(WindowEventsModule.js)

import {Module} from 'react-vr-web';
import lodash from 'lodash';

const eventToOb = (event) => {
    const eventOb = {};
    for (let key in event) {
        const val = event[key];
        if (!(lodash.isFunction(val) || lodash.isObject(val))) {
            eventOb[key] = val;
        }
    }
    return eventOb;
};

export default class WindowEventsModule extends Module {
    constructor() {
        super('WindowEventsModule');

        this._bridgeName = 'BrowserBridge';

        window.onmousewheel = event => {
            this._emit('onmousewheel', event);
        };
    }

    init(rnctx) {
        this._rnctx = rnctx;
    }

    _emit(name, event) {
        if (!this._rnctx) {
            return;
        }

        const eventOb = eventToOb(event);

        this._rnctx.callFunction(this._bridgeName, 'notifyEvent', [name, eventOb]);
    }
}

这感觉非常hacky,因为它似乎不会被BatchedBridge暴露给消费者。

但是在有更好的选择之前,我想我会选择这个。