vue和app之间的通信,涵盖双向通信、异步回调、错误处理和日志记录等功能。
以下是重新设计的封装方案,涵盖双向通信、异步回调、错误处理和日志记录等功能。
Vue.js 与原生 APP 通信封装方案
1. 需求概述
在混合开发中,Vue.js 前端页面需要与原生 APP 进行通信,常见的需求包括:
-
从 Vue 向原生发送数据(如用户操作、请求原生功能)。
-
从原生向 Vue 发送数据(如原生状态更新、回调)。
-
触发原生页面或功能(如打开设置、调用摄像头)。
-
跨平台兼容性(iOS 和 Android)。
-
支持异步回调(原生调用 Vue 方法)。
-
错误处理与日志记录(便于调试)。
2. 封装设计
我们将封装一个通用的通信模块 NativeBridge,并拆分为以下子模块:
-
NativeBridge:核心通信模块,封装发送消息、接收消息、调用原生方法等功能。 -
NativeLogger:日志记录模块,用于记录通信过程中的信息和错误。 -
NativeCallbackManager:异步回调管理模块,支持原生调用 Vue 方法。
3. 代码实现
3.1 NativeLogger.js
日志记录模块,用于记录通信过程中的信息和错误。
// NativeLogger.js
const log = {
info(message) {
console.log(`[NativeBridge] INFO: ${message}`);
},
error(message) {
console.error(`[NativeBridge] ERROR: ${message}`);
}
};
export default log;
3.2 NativeCallbackManager.js
异步回调管理模块,支持原生调用 Vue 方法。
// NativeCallbackManager.js
const callbacks = {};
export const registerCallback = (callback) => {
const callbackId = Date.now().toString(36); // 生成唯一回调 ID
callbacks[callbackId] = callback;
return callbackId;
};
export const invokeCallback = (callbackId, data) => {
if (callbacks[callbackId]) {
callbacks[callbackId](data);
delete callbacks[callbackId];
}
};
3.3 NativeBridge.js
核心通信模块,封装发送消息、接收消息、调用原生方法等功能。
// NativeBridge.js
import log from "./NativeLogger";
import { registerCallback, invokeCallback } from "./NativeCallbackManager";
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
const isAndroid = /Android/.test(navigator.userAgent);
const platform = isIOS ? "iOS" : isAndroid ? "Android" : null;
export const sendMessageToNative = (data, callback) => {
if (!platform) {
log.error("Unsupported platform");
return;
}
try {
const callbackId = callback ? registerCallback(callback) : null;
const message = { data, callbackId };
if (isIOS) {
window.webkit.messageHandlers.nativeListener.postMessage(message);
} else if (isAndroid) {
window.parent.postMessage(message, "*");
}
log.info(`Message sent to native: ${JSON.stringify(data)}`);
} catch (error) {
log.error(`Failed to send message: ${error.message}`);
}
};
export const receiveMessageFromNative = (callback) => {
window.addEventListener("message", (event) => {
if (event.source === window.parent) {
try {
const { data, callbackId } = event.data;
log.info(`Message received from native: ${JSON.stringify(data)}`);
if (callbackId) {
invokeCallback(callbackId, data);
} else {
callback(data);
}
} catch (error) {
log.error(`Failed to handle message: ${error.message}`);
}
}
});
};
export const callNativeMethod = (methodName, data) => {
if (!platform) {
log.error("Unsupported platform");
return;
}
try {
if (isIOS) {
window.webkit.messageHandlers[methodName].postMessage(data);
} else if (isAndroid) {
window.nativeBridge[methodName](data);
}
log.info(`Called native method: ${methodName}`);
} catch (error) {
log.error(`Failed to call native method: ${error.message}`);
}
};
4. 在 Vue 组件中使用
4.1 Vue 组件示例
在 Vue 组件中,可以通过导入 NativeBridge 模块来使用封装好的通信功能。
<template>
<div>
<button @click="sendMessage">Send Message to Native</button>
<button @click="openNativePage">Open Native Page</button>
<button @click="callNativeMethod">Call Native Method</button>
</div>
</template>
<script>
import { sendMessageToNative, receiveMessageFromNative, callNativeMethod } from "./NativeBridge";
export default {
mounted() {
// 监听原生发送的消息
receiveMessageFromNative((message) => {
console.log("Received message from native:", message);
});
},
methods: {
sendMessage() {
// 向原生发送消息并接收回调
sendMessageToNative({ text: "Hello from Vue!" }, (response) => {
console.log("Native response:", response);
});
},
openNativePage() {
// 触发原生页面
window.location.href = "myapp://openPage";
},
callNativeMethod() {
// 调用原生方法
callNativeMethod("sendMessage", { text: "Hello from Vue!" });
},
},
};
</script>
5. 原生端实现
5.1 iOS 实现
在 iOS 中,通过 WKWebView 和 WKScriptMessageHandler 接收和处理消息。
import WebKit
class ViewController: UIViewController, WKScriptMessageHandler {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let config = WKWebViewConfiguration()
let userContentController = WKUserContentController()
userContentController.add(self, name: "nativeListener")
userContentController.add(self, name: "sendMessage")
config.userContentController = userContentController
webView = WKWebView(frame: self.view.bounds, configuration: config)
view.addSubview(webView)
webView.load(URLRequest(url: URL(string: "https://your-vue-app.com")!))
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "nativeListener" {
if let body = message.body as? [String: Any] {
print("Received message: \(body)")
// 处理消息
if let callbackId = body["callbackId"] as? String {
webView.evaluateJavaScript("window.invokeCallback('\(callbackId)', { response: 'Hello from iOS!' })")
}
}
} else if message.name == "sendMessage" {
if let body = message.body as? [String: Any] {
print("Received message: \(body)")
// 处理消息
}
}
}
}
5.2 Android 实现
在 Android 中,通过 addJavascriptInterface 暴露原生方法。
import android.webkit.WebView;
import android.webkit.JavascriptInterface;
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new NativeBridge(), "nativeBridge");
webView.loadUrl("https://your-vue-app.com");
}
public class NativeBridge {
@JavascriptInterface
public void sendMessage(String message, String callbackId) {
// 处理消息
Log.d("NativeBridge", "Received message: " + message);
webView.evaluateJavascript("javascript:invokeCallback('" + callbackId + "', { response: 'Hello from Android!' })", null);
}
}
}
6. 进一步扩展
如果需要更高级的功能,比如文件传输、状态同步等,可以在 NativeBridge.js 中添加更多的方法。例如:
export const uploadFileToNative = (file) => {
if (!platform) {
log.error("Unsupported platform");
return;
}
try {
if (isIOS) {
window.webkit.messageHandlers.uploadFile.postMessage(file);
} else if (isAndroid) {
window.nativeBridge.uploadFile(file);
}
log.info(`File upload request sent`);
} catch (error) {
log.error(`Failed to upload file: ${error.message}`);
}
};
7. 总结
通过模块化设计和功能拆分,我们优化了 Vue.js 与原生 APP 的通信模块,使其具备以下特点:
-
异步回调支持:支持原生调用 Vue 方法。
-
错误处理与日志记录:便于调试和问题排查。
-
灵活的双向通信:支持多种通信方式,包括消息传递、URL Scheme 和原生方法调用。
-
易扩展性:模块化设计使得功能扩展更加方便。
更多推荐


所有评论(0)