第一部分,在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)
//注册事件(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