使用方法
- 原生
class ViewController: UIViewController {
let webView = ...
var bridge: WKWebviewJavascriptBridge!
...
override func viewDidLoad() {
super.viewDidLoad()
bridge = WKWebViewJavascriptBridge(webview: webView)
bridge.register(handlerName: "xxx") { params, callback in
}
}
...
func click() {
bridge.call(handlerName: "xxxx") { params, callback in
}
}
}
复制代码
vue
改造
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
return callback(window.WebViewJavascriptBridge);
}
if (window.WVJBCallbacks) {
return window.WVJBCallbacks.push(callback);
}
window.WVJBCallbacks = [callback];
let WVJBIframe = document.createElement("iframe");
WVJBIframe.style.display = "none";
WVJBIframe.src = "https://__bridge_loaded__";
document.documentElement.appendChild(WVJBIframe);
setTimeout(() => {
document.documentElement.removeChild(WVJBIframe);
}, 0);
}
const callhandler = (name, data, callback) => {
setupWebViewJavascriptBridge(function(bridge) {
bridge.callHandler(name, data, callback);
});
};
const registerhandler = (name, callback) => {
setupWebViewJavascriptBridge(function(bridge) {
bridge.registerHandler(name, function(data, responseCallback) {
callback(data, responseCallback);
});
});
};
export { registerhandler, callhandler };
复制代码
vue
中使用
import { callhandler, registerhandler } from './bridge';
...
mounted() {
registerhandler(<name>, () => {
});
},
methods: {
callMobile() {
callhandler(<name>, params, (result) => {
});
}
}
复制代码
或者 在 main.js
中
import Bridge from './bridge.js'
Vue.prototype.$bridge = Bridge
this.$bridge.callhandler(...)
this.$bridge.register(...)
复制代码
原生通信
当我们不借助这个三方库,我们原生应该怎样直接交互呢?
js 调用原生
- js
// 这里需要注意如果 messageBody 有且必须有一个参数,如果不需要就传 null
// <name> 就是和移动端协商的函数名
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
复制代码
- 原生
class ViewController: UIViewController {
override func viewdidLoad() {
super.viewDidLoad()
// 这里有个细节就是需要注意循环引用的问题
webView?.configuration.userContentController.add(LeakAvoider(delegate: self), name: <name>)
}
// 这里一定要记得释放
deinit {
webView?.configuration.userContentController.removeScriptMessageHandler(forName: <name>)
}
}
extension ViewController: WKScriptMessageHandler {
public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == <name> {
// doSomething(message.body)
}
}
复制代码
原生调用 js
- 原生
webview.evaluateJavaScript(<name>, completionHandler: completion)
复制代码
- js
window.<name> = function(param) {
// doSomething()
}
复制代码
原理
初始化
js
调用window.webkit.messageHandlers.iOS_Native_InjectJavascript.postMessage(null)
iOS
执行webView.evaluateJavascript(javascript: WKWebViewJavascriptBridgeJS, ...)
这样在 js
和原生都会有一个 messageHandlers
和 responseCallbacks
,后续可以根据字符串去匹配对应的函数执行,并且会有一个自增的 uniqeID
记录对应的回调。