端能力是 App 开发中非常重要的基础技术,在 js-native 这种框架研发过程中要保证多端统一,也就是说在 H5 页面中当调用一个端能力的时候,需要提供统一的调用 API,如下:
// bad
function getSystemInfo() {
if (isIos) {
// send msg to iOS
}
else if (isAndroid) {
// send msg to android
}
}
// good
function getSystemInfo() {
// send msg to all platform
}
要想保证 API 的一致性,必须对 JS 与 Native 通信的方式有一个彻底的了解。我主要了解到以下几种通信方式:
postMessage(iOS WKWebview)
这种方式是在 iOS 中处理消息非常方便,但是在 Android 中并不支持。
- (void)userContentController:(WKUserContentController *)uc
didReceiveScriptMessage:(WKScriptMessage *)message
{
// 接收到消息,并处理
}
// 消息发送
window.webkit.messageHandlers.SYJSBridge.postMessage(msg);
prompt(iOS/Android Webview)
巧用 webview 的弹窗,弹窗内容定义消息体,显然这种方式对于处理消息很不方便,纯粹的做字符串解析。
前端实现(消息发送):
window.prompt(msg);
iOS 端实现(接收消息):
- (void)webView:(WKWebView *)webView
runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt
defaultText:(NSString *)defaultText
initiatedByFrame:(WKFrameInfo *)frame
completionHandler:(void (^)(NSString *))completionHandler
{
completionHandler(@"OC input");
}
iframe(iOS/Android Webview)
创建一个隐形的 iframe,Native 侧会收到一个请求,可以通过请求地址来做一个处理,达到通信的目的。
前端调用实现(发送消息)
// js 侧进行消息发送
const callIframe = function(url) {
var iframe = document.createElement('iframe');
iframe.src = url;
document.body.appendChild(iframe);
document.body.removeChild(iframe);
}
iOS 端实现(接收消息):
// native 接收到消息
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)na
decisionHandler:(void (^)(WKNavigationActionPolicy))h {
NSLog(@"%@", NSStringFromSelector(_cmd));
decisionHandler(WKNavigationActionPolicyAllow);
}
注入 JS(iOS WKWebView)
这种方式主要通过 webview 提供的 API 向 JavaScript 执行引擎中注入 JavaScript 代码。下面的代码在页面加载时注入了一个 add 函数,这个函数被挂载到了 window 下,在网页中可直接调用。
iOS 端实现:
WKUserScript *script = [[WKUserScript alloc]
initWithSource:@"function add(a, b) { return a + b; }"
injectionTime:WKUserScriptInjectionTimeAtDocumentStart
forMainFrameOnly:YES];
[webview.configuration.userContentController addUserScript:script];
location.href(iOS/Android Webview)
这种方式和第 3 种方法类似,不过需要对做通信 API 的路由做拦截处理,否则会跳转到新的页面。下面我简单处理了这个过程:
前端调用实现(发送消息):
window.location.href = url;
iOS 端实现(接收消息):
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)na
decisionHandler:(void (^)(WKNavigationActionPolicy))d {
NSLog(@"%@", NSStringFromSelector(_cmd));
if ([na.request.URL.absoluteString containsString:@"suyan"]) {
d(WKNavigationActionPolicyCancel);
}
else {
d(WKNavigationActionPolicyAllow);
}
}
addJavaScriptInterface(Android Webview)
把一个 Java 对象注入到 JavaScript 执行环境当中,使得在 webivew 中可直接调用该方法,间接调用 Native 方法。
参考:
https://github.com/ecomfe/js-native

长按关注
素燕《前端小课》
帮助 10W 人入门并进阶前端
本文介绍了6种JS与Native通信的方式,包括postMessage、prompt、iframe、注入JS、location.href以及addJavaScriptInterface,详细讲解了每种方式的实现原理和应用场景,适用于多端统一的App开发中确保API的一致性。
1万+

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



