背景介绍
在混合开发中,H5 页面与原生应用的通信是一个常见需求。本文将详细介绍如何实现 H5 与 React Native WebView 之间的双向通信机制。
核心实现
首先,我们需要在 H5 端实现一个回调管理器,用于处理与原生端的通信:
1. H5 端完整实现
// 回调管理器
window.NativeCallbacks = {
callbacks: {},
register: function(type, successCallback, errorCallback) {
const callbackId = type + Date.now().toString();
// Promise方式
if (!successCallback && !errorCallback) {
const promise = new Promise((resolve, reject) => {
this.callbacks[callbackId] = {
success: resolve,
error: reject,
};
});
return {
promise,
callbackId
};
}
// 回调方式
this.callbacks[callbackId] = {
success: successCallback,
error: errorCallback,
};
return callbackId;
},
execute: function(callbackId, type, data) {
const callback = this.callbacks[callbackId];
if (callback) {
if (type === 'success') {
callback.success && callback.success(data);
} else {
callback.error && callback.error(data);
}
delete this.callbacks[callbackId]; // 执行后清理回调
}
}
};
// 原生通信接口封装
window.Native = {
// 回调方式
getUserInfo: function(successCallback, errorCallback) {
const callbackId = ntalkCallbacks.register('getUserInfo', successCallback, errorCallback);
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'getUserInfo',
callbackId,
data: null
}));
},
// Promise方式
getUserInfoAsync: async function() {
const { promise, callbackId } = ntalkCallbacks.register('getUserInfo');
window.ReactNativeWebView.postMessage(JSON.stringify({
type: 'getUserInfo',
callbackId,
data: null
}));
return promise;
}
};
2. React Native 端完整实现
interface MessageData {
type: string;
callbackId: string;
data: any;
}
class WebViewManager {
private webview: WebView;
constructor(webview: WebView) {
this.webview = webview;
}
handleMessage(message: string) {
try {
const data: MessageData = JSON.parse(message);
const { type, callbackId, data: payload } = data;
switch(type) {
case 'getUserInfo':
this.handleGetUserInfo(callbackId, payload);
break;
case 'setAppCacheValue':
this.handleSetAppCache(callbackId, payload);
break;
default:
this.sendCallback(callbackId, 'error', '未知的消息类型');
}
} catch (error) {
console.error('消息处理错误:', error);
}
}
sendCallback(callbackId: string, type: 'success' | 'error', data: any) {
const script = `
window.ntalkCallbacks.execute(
'${callbackId}',
'${type}',
${JSON.stringify(data)}
);
`;
this.webview.injectJavaScript(script);
}
private handleGetUserInfo(callbackId: string, payload: any) {
try {
// 实际项目中从本地存储或状态管理中获取
const userInfo = {
userId: '123',
name: '张三',
avatar: 'https://example.com/avatar.png'
};
this.sendCallback(callbackId, 'success', userInfo);
} catch (error) {
this.sendCallback(callbackId, 'error', error.message);
}
}
private handleSetAppCache(callbackId: string, payload: any) {
try {
const { key, value } = payload;
// 实际项目中进行缓存操作
this.sendCallback(callbackId, 'success', true);
} catch (error) {
this.sendCallback(callbackId, 'error', error.message);
}
}
}
// WebView 组件使用示例
function MyWebView() {
const webViewRef = useRef<WebView>(null);
const webViewManager = useRef<WebViewManager>();
useEffect(() => {
if (webViewRef.current) {
webViewManager.current = new WebViewManager(webViewRef.current);
}
}, []);
return (
<WebView
ref={webViewRef}
source={{ uri: 'https://example.com' }}
onMessage={(event) => {
webViewManager.current?.handleMessage(event.nativeEvent.data);
}}
/>
);
}
3. 使用示例
// 示例1:回调方式
Native.getUserInfo(
(userInfo) => {
console.log('获取用户信息成功:', userInfo);
},
(error) => {
console.error('获取用户信息失败:', error);
}
);
// 示例2:Promise方式
async function getUserData() {
try {
const userInfo = await ntalkNative.getUserInfoAsync();
console.log('获取用户信息成功:', userInfo);
} catch (error) {
console.error('获取用户信息失败:', error);
}
}
1万+

被折叠的 条评论
为什么被折叠?



