ReactNative中js与原生如何交互

第一部分,在ReactNative中,原生与js交互常用的是原生通过向js发送事件,参考webview源代码。

1、定义事件与发送消息方法

public class ReactExpandListViewEvent extends Event {

    public static final String EVENT_NAME = "topExpandListViewClick";

    private WritableMap mEventData;

    public ReactExpandListViewEvent(int viewId, WritableMap eventData) {
        super(viewId);
        mEventData = eventData;
    }

    @Override
    public String getEventName() {
        return EVENT_NAME;
    }

    @Override
    public void dispatch(RCTEventEmitter rctEventEmitter) {
        rctEventEmitter.receiveEvent(getViewTag(), getEventName(), mEventData);
    }
}
2、注册事件(topExpandListViewClick)
在ViewManager重写以下方法

    //注册事件(ReactExpandListViewEvent)
    @Override
    public Map getExportedCustomDirectEventTypeConstants() {
        return MapBuilder.builder()
                .put("topExpandListViewClick", MapBuilder.of("registrationName", "onExpandListViewClick"))
                .build();
    }
3、组装发送到js的数据

在ViewManger中组装数据

    //组装发送到js的数据
    private WritableMap createExpandListViewEvent(ExpandableListView expandListView) {
        WritableMap event = Arguments.createMap();
        event.putDouble("target", 2222222);
        event.putString("url", "22222");
        event.putBoolean("loading", true);
        event.putDouble("width", expandListView.getWidth());
        return event;
    }
4、ViewManger发送事件给js

    public void emitExpandListViewEvent(ExpandableListView expandListView) {
        dispatchEvent(expandableListView, new ReactExpandListViewEvent(expandListView.getId(), createExpandListViewEvent(expandListView)));
    }

    //发送事件到js
    private static void dispatchEvent(ExpandableListView expandableListView, Event event) {
        ReactContext reactContext = (ReactContext) expandableListView.getContext();
        EventDispatcher eventDispatcher =
                reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
        eventDispatcher.dispatchEvent(event);
    }
5、js组件侦听

'use strict';

import React from 'react';
import { PropTypes } from 'react';
import ReactNative from 'react-native';
import {
    ViewPropTypes,
    StyleSheet,
    UIManager,
    View,
    requireNativeComponent,
    DeviceEventEmitter,
} from 'react-native';

var RCT_EXPANDABLELISTVIEW_REF = 'expandableListView';

class ExpandableListView extends React.Component {
  static propTypes = {
    ...ViewPropTypes,
    layoutWidth:  PropTypes.number,
    layoutHeight: PropTypes.number,
  };

  render() {
    var expandableListViewStyles = [styles.container, this.props.style];
    var expandableListView =
      ;

    return (
      
        {expandableListView}
      
    );
  }

  goExpand = () => {
    //console.log("1111");
    UIManager.dispatchViewManagerCommand(
      this.getExpandableListViewHandle(),
      UIManager.RCTExpandableListView.Commands.goExpand,
      null
    );
  };

  postMessageExpand = () => {
    UIManager.dispatchViewManagerCommand(
      this.getExpandableListViewHandle(),
      UIManager.RCTExpandableListView.Commands.postMessageExpand,
      null
    );
  };

  injectJavaScriptExpand = (data) => {
    UIManager.dispatchViewManagerCommand(
      this.getExpandableListViewHandle(),
      UIManager.RCTExpandableListView.Commands.injectJavaScriptExpand,
      [data]
    );
  };

  /**
   * We return an event with a bunch of fields including:
   *  url, title, loading, canGoBack, canGoForward
   */
  updateNavigationState = (event) => {
    if (this.props.onNavigationStateChange) {
      this.props.onNavigationStateChange(event.nativeEvent);
    }
  };

  getExpandableListViewHandle = () => {
    return ReactNative.findNodeHandle(this.refs[RCT_EXPANDABLELISTVIEW_REF]);
  };

  onExpandListViewClick = (event: Event) => {
    console.log("onExpandListViewClick------------->"+event.nativeEvent.url);
    var onExpandListViewClick = this.props.onExpandListViewClick;
    onExpandListViewClick && onExpandListViewClick(event);
    this.updateNavigationState(event);
  };
}

var RCTExpandableListView = requireNativeComponent('RCTExpandableListView', ExpandableListView, {});

var styles = StyleSheet.create({
  /*
  container: {
    flex: 1,
  },
  */
});

module.exports = ExpandableListView;
第二部分,js可以通过命令的形式来调用原生(先除掉调用原生方法与自定义组件)

1、ViewManger重写以下方法,分为注册命令与接收js发送的命令

   //注册命令
    @Override
    public @Nullable
    Map getCommandsMap() {
        return MapBuilder.of(
                "goExpand", COMMAND_GO_BACK,
                "postMessageExpand", COMMAND_POST_MESSAGE,
                "injectJavaScriptExpand", COMMAND_INJECT_JAVASCRIPT
        );
    }

    //接收命令;js通过命令来操作(比如ReactNative页面上有个
    // 前进按钮点击后可以触发这些命令)
    @Override
    public void receiveCommand(ExpandableListView root, int commandId, @Nullable ReadableArray args) {
        switch (commandId) {
            case COMMAND_GO_BACK:
                UiThreadUtil.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(activity, "hello", Toast.LENGTH_SHORT).show();
                    }
                });
                break;
            case COMMAND_POST_MESSAGE:
                try {
                    JSONObject eventInitDict = new JSONObject();
                    eventInitDict.put("data", args.getString(0));
                    Toast.makeText(activity,eventInitDict.toString(),Toast.LENGTH_SHORT);
                    /*
                    root.loadUrl("javascript:(function () {" +
                            "var event;" +
                            "var data = " + eventInitDict.toString() + ";" +
                            "try {" +
                            "event = new MessageEvent('message', data);" +
                            "} catch (e) {" +
                            "event = document.createEvent('MessageEvent');" +
                            "event.initMessageEvent('message', true, true, data.data, data.origin, data.lastEventId, data.source);" +
                            "}" +
                            "document.dispatchEvent(event);" +
                            "})();");
                            */
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
                break;
            case COMMAND_INJECT_JAVASCRIPT:
                //root.loadUrl("javascript:" + args.getString(0));
                break;
        }
    }
2、js发送命令

参考第一部分第五条js组件侦听中的方法goExpand等

具体代码可以参考Git:https://github.com/Springever/Test

你可能感兴趣的:(ReactNative)