JavaScript与原生交互
2019-03-29 本文已影响0人
今晚月色
实例样式
原生页面与HTML页面进行相互调用
方式 | 适用对象 |
---|---|
拦截URL |
UIWebView 和WKWebView
|
JavaScriptCore | UIWebView |
MessageHandler | WKWebView |
WebViewJavascriptBridge |
UIWebView 和WKWebView
|
实例HTML代码
<body>
<h2>按钮点击</h2>
<button type="submit" onclick="buttonEvent()" id="submitButto">提交</button>
<h2>文件上传</h2>
<input type="file" />
<h2>原生注入数据</h2>
<input type="text" id="textField">
<input type="button" onclick="getTextEvent()" value="开始注入">
<script>
function loadURL(url) {
var iFrame;
iFrame = document.createElement("iframe");
iFrame.setAttribute("src", url);
iFrame.setAttribute("style", "display:none;");
iFrame.setAttribute("height", "0px");
iFrame.setAttribute("width", "0px");
iFrame.setAttribute("frameborder", "0");
document.body.appendChild(iFrame);
iFrame.parentNode.removeChild(iFrame);
iFrame = null;
}
function buttonEvent(){
loadURL("/buttonEvent");
buttonDidPapped();
}
function getTextEvent() {
loadURL("/getText");
getTextButtonDidPapped();
}
function getText(text){
document.getElementById("textField").value = text;
}
</script>
</body>
拦截URL
UIWebView
遵循UIWebViewDelegate
调用- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
方法,判断获取的Url地址
// 调用JS
if ([request.URL.absoluteString hasSuffix:@"buttonEvent"]) {
UIAlertController *vc = [UIAlertControlleralertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
[vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:vc animated:true completion:nil];
return NO;
}
// 注入数据给JS
if ([request.URL.absoluteString hasSuffix:@"getText"]) {
[webView stringByEvaluatingJavaScriptFromString:@"getText('哈哈')"];
return NO;
}
return YES;
WKWebView
遵循WKNavigationDelegate
调用- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
方法判断获取的地址
NSString *strRequest = [navigationAction.request.URL.absoluteString stringByRemovingPercentEncoding];
// 调用JS
if ([strRequest hasSuffix:@"buttonEvent"]) {
UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
[vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:vc animated:true completion:nil];
decisionHandler(WKNavigationActionPolicyCancel);
} else if ([strRequest hasSuffix:@"getText"]) { // 注入数据给JS
[webView evaluateJavaScript:@"getText('哈哈')" completionHandler:^(id _Nullable info, NSError * _Nullable error) {
NSLog(@"Error--%@, info--%@", error, info);
}];
decisionHandler(WKNavigationActionPolicyCancel);
} else {
decisionHandler(WKNavigationActionPolicyAllow);
}
JavaScriptCore
- 导入
<JavaScriptCore/JavaScriptCore.h>
- 遵循
<UIWebViewDelegate>
并实现- (void)webViewDidFinishLoad:(UIWebView *)webView
方法。
// 对JSContext对象进行初始化
JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
// 验证JSContext对象是否初始化成功
context.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue){
context.exception = exceptionValue;
};
// 调用JS
context[@"buttonDidPapped"] = ^{
UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
[vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:vc animated:true completion:nil];
};
// 注入数据给JS
context[@"getTextButtonDidPapped"] = ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self.webView stringByEvaluatingJavaScriptFromString:@"getText('哈哈')"];
});
};
MessageHandler
- 修改js中的方法, 通过
window.webkit.messageHandlers
+操作方法
function buttonEvent(){
window.webkit.messageHandlers.buttonEvent.postMessage(null);
}
function getTextEvent() {
window.webkit.messageHandlers.getTextEvent.postMessage(null);
}
- 遵循
WKScriptMessageHandler
- 在
- (void)viewWillAppear:(BOOL)animated
中添加scriptMessageHandler
- 在
- (void)viewWillDisappear:(BOOL)animated
中移除scriptMessageHandler
- 实现
WKScriptMessageHandler
方法
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"buttonEvent"];
[self.webView.configuration.userContentController addScriptMessageHandler:self name:@"getTextEvent"];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"buttonEvent"];
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"getTextEvent"];
}
#pragma mark - WKScriptMessageHandler Method
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
// 调用JS
if ([message.name isEqualToString:@"buttonEvent"]) {
UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
[vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:vc animated:true completion:nil];
return;
}
// 注入数据给JS
if ([message.name isEqualToString:@"getTextEvent"]) {
[self.webView evaluateJavaScript:@"getText('哈哈')" completionHandler:^(id _Nullable info, NSError * _Nullable error) {
NSLog(@"Error--%@, info--%@", error, info);
}];
return;
}
}
WebViewJavascriptBridge
HTML代码
<body>
<h2>按钮点击</h2>
<input id = 'submitBtn' type="button" value="提交按钮" onclick="submitClick()"/>
<h2>文件选择</h2>
<input type="file" id="image">
<h2>注入数据</h2>
<input type="text" id="getTextField" />
<input type="button" value="开始获取" id = 'startGet' onclick="getTextClick()"/>
<script>
function setupWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
window.WVJBCallbacks = [callback];
var WVJBIframe = document.createElement('iframe');
WVJBIframe.style.display = 'none';
WVJBIframe.src = 'https://__bridge_loaded__';
document.documentElement.appendChild(WVJBIframe);
setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}
setupWebViewJavascriptBridge(function(bridge) {
})
function submitClick() {
WebViewJavascriptBridge.callHandler('submitClick', null, function(response) {
});
}
function getTextClick() {
WebViewJavascriptBridge.callHandler('getTextClick', null, function(response) {
document.getElementById("getTextField").value = response;
});
}
</script>
</body>
第三方库:地址
- 添加
WebViewJavascriptBridge
库 - 导入头文件
#import <WebViewJavascriptBridge.h>
- 声明方法
@property WebViewJavascriptBridge* bridge;
- 与WebView关联
_bridge = [WebViewJavascriptBridge bridgeForWebView:self.webView];
[_bridge setWebViewDelegate:self];
- 调用js
[_bridge registerHandler:@"submitClick" handler:^(id data, WVJBResponseCallback responseCallback) {
UIAlertController *vc = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"点击了提交按钮" preferredStyle:UIAlertControllerStyleAlert];
[vc addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:vc animated:true completion:nil];
}];
- 注入数据
[_bridge registerHandler:@"getTextClick" handler:^(id data, WVJBResponseCallback responseCallback) {
responseCallback(@"哈哈哈");
}];