首先要理清一下关系:
HTML:一些网页控件。
超文本标记语言,标准通用标记语言(SGM或SGML)下的一个应用。
“超文本”就是指 页面内可以包含图片、链接,甚至音乐、程序 等非文字元素。
超文本标记语言的结构包括: “头”部分(英语:Head)、“主体”部分(英语:Body)。其中“头”部提供关于网页的信息,“主体”部分提供网页的具体内容。
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
html代码
</body>
</html>
<!--中间的内容为注释-->
“<!DOCTYPE html>
”作用:声明文档的解析类型(document.compatMode),避免浏览器的怪异模式 (等同于开启了标准模式) 。
CSS (层叠样式表):是美化控件的代码。 (英文全称:Cascading Style Sheets)
是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。
js(javascript):一种增强表现力的脚本语言,可以做出很多动态 及 交互性较强 的效果。
JavaScript是一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页 增加动态功能。
JavaScript基于对象(Object)和事件驱动(Event Driven)并具有安全性能的脚本语言。使用它的目的是与HTML超文本标记语言、Java脚本语言(Java小程序)一起实现在一个Web页面 中 链接 多个对象,与Web客户 进行交互作用。
HTML的文档结构:
head元素的标记语法图:
进入主题:如果在项目中使用HTML格式(比如:现在大火的HTML5),往往涉及到OC与JS的交互。
html页面 不仅仅满足展示 功能,也能 与原生语言进行交互、相互传值。
-
从OC到JS,可以使用“
[ stringByEvaluatingJavaScriptFromString:]
”方法执行JavaScript语句的字符串 来实现。
- 从JS到OC,通过UIWebView浏览器 拦截url请求,自定义url的方式 拦截 交互请求。
交互常见形式
[一].UIWebView Delegate
-
1.过滤 请求条件:
一般在 “-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { }
” 方法里!// 禁止webview中的链接点击 (用于 :⭐️过滤 请求条件) -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType { // 页面准备加载内容时调用,通过返回值来进行判断是否要加载 if (webView == self.webV_2) { // 是第二个WebView if(navigationType == UIWebViewNavigationTypeLinkClicked) { //判断点击的是否为 链接 return NO; //返回“NO”,不加载到链接的页面 }else{ return YES; } } else { // 其他WebView可以响应 链接 return YES; } }
加载效果:
第二个WebView每次点击到响应的类型,都会判断是否为“链接”类型:如果是,不予响应(进入链接页面)。
-
2.JavaScript处理:
一般在 “-(void)webViewDidFinishLoad:(UIWebView *)webView { }
” 方法里!-(void)webViewDidFinishLoad:(UIWebView *)webView { // 加载完后触发 if (webView == self.webV_2) { // 是第二个WebView NSString * fontStr = @"document.getElementsByTagName('body')[0].style.webkitTextSizeAdjust= '50%'";//字体大小 // JavaScript设置:字体大小设置为 50% [self.webV_2 stringByEvaluatingJavaScriptFromString:fontStr]; } }
效果:
通过JavaScript语句,设置字体大小为50%。
请参考:《UIWebView的使用》
[二].JavaScriptCore框架
添加“JavaScriptCore.frame”框架:
头文件:#import <JavaScriptCore/JavaScriptCore.h>
步骤:
- 1.在HTML文件中,注册 组件 (如按钮等)。
- 2.在“
- (void)webViewDidFinishLoad:(UIWebView *)webView{ }
”方法里面通过JSContext来获取 相应操作的key值(为 HTML文件中点击方法的名字),并调用相应的操作。
//JS上下文
@property (nonatomic,strong) JSContext *context;
JS调用OC的函数:
方法一
使用“
self.context[@"key值] = ^{ };
” 截取方法<html> <meta charset="UTF-8"> <head lang="en"> <meta charset="UTF-8"> <h1 style='color:blue'> OC与JS交互 </h1> <!-- 再本层目录里操作,所以src不用加目录,同样css也是一样的 --> <script type="text/javascript" src="" charset="UTF-8"></script> <script type="text/javascript"> function clickLink(){ } </script> <css type="text/css" charset="UTF-8"> <!-- 中间的内容是css代码 --> </css> <html type="text/html" src="MyCreate.js" charset="UTF-8"> <!-- 中间的内容是html代码 --> </html> </head> <body> <h2>标题66666</h2> <!-- 二级标题 --> <p> <p style='color:red'> <!-- 颜色改变 --> Use of JavaScript and Objective-C </p> <input type="button" value="点击" onclick="clickLink()" /> <br/> <input type="button" value="打印" onclick="clickLink('hello!abc~')" /> <br/> <!-- 返回字符串:'你好!abc~' --> </body> </html>
在“- (void)viewDidLoad { }
”里,按自己的路径来加载“MyCreateFile.html”文件:NSString *path = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"MyCreateFile.html"]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]; [self.myWebV loadRequest:request];
在“- (void)webViewDidFinishLoad:(UIWebView *)webView { }
”里面://截取 JavaScript self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; self.context[@"clickLink"] = ^{ //截取按钮点击操作 NSArray *arg = [JSContext currentArguments]; NSLog(@"数组:%@",arg); for (id obj in arg) { NSLog(@"obj is:%@", obj); } };
打印结果:
方法二
使用
<JSExport>
协议
可以直接在当前视图控制器 里 写上协议的响应方法,也可以封装一个类专门来处理。头文件:
#import <JavaScriptCore/JavaScriptCore.h>
例子🌰
html文件:
body部分
<body> <div id="question"> <div class="info"> <div class="topic topicFill"> <input type="hidden" class="questionId" name="questionId" value="8bf928be53b142f9bcd51324bf4a7422" /> <input type="hidden" class="defaultNum" name="answer" value="" /> <span class="topicInfo">测试数据问答题</span> <textarea name="theAnswer" placeholder="请输入……"></textarea> </div> </div> <div class="footer"> <button class="saveBtn" id="saveBtn" onclick="saveUser()"> <span>保存</span> </button> <button class="submitBtn" id="submitBtn" onclick="submit()"> <span>提交</span> </button> </div> </div> </body>
js部分
function saveUser() { //提交表单 (保存数据) //数据处理操作 // ………… //处理好之后的数据 var myData = { "token" : token, "templateId" : templateId, "answers" : answer, "id" : id, "type" : type }; var myJson = JSON.stringify(myData); //console.log(JSON.stringify(myJson)); if(answer != null && answer.length >= 0){ $.ajax({ //ajax网络请求 cache : true, type : "post", contentType : "application/x-www-form-urlencoded", url : '/applications/html/preservation', dataType:'json', data:{'data':myJson}, async:false, cache:false, error : function(request) { Android.requestSaveTouchEvent(false,"服务器链接失败!"); }, success : function(data) { if(data.Code == 0){ Android.requestSaveTouchEvent(true,data.CodeMsg); }else{ Android.requestSaveTouchEvent(false,data.CodeMsg); } } }); } } function submit() { //提交表单(上传数据) //数据处理操作 // ………… //处理好之后的数据 var myData = { "token" : token, "templateId" : templateId, "answers" : answer, "id" : id, "type" : type }; var myJson = JSON.stringify(myData); //console.log(JSON.stringify(myJson)); if(answer != null && answer.length >= 0){ $.ajax({ //ajax网络请求 cache : true, type : "post", contentType : "application/x-www-form-urlencoded", url : '/applications/html/submit', dataType:'json', data:{'data':myJson}, async:false, cache:false, error : function(request) { Android.requestSubmitTouchEvent(false,"服务器链接失败!"); }, success : function(data) { /* console.log(data); alert(data.CodeMsg); */ if(data.Code == 0){ $(".footer").remove(); Android.requestSubmitTouchEvent(true,data.CodeMsg); }else{ Android.requestSubmitTouchEvent(false,data.CodeMsg); } } }); } }
新建“JSObject”类:
在
JSObject.h
`文件:#import <Foundation/Foundation.h> #import <JavaScriptCore/JavaScriptCore.h> //首先创建一个实现了JSExport协议的协议 @protocol JSObjectProtocol <JSExport> -(void)requestSaveTouch:(BOOL)isSuccess Event:(NSString *)notice; -(void)requestSubmitTouch:(BOOL)isSuccess Event:(NSString *)notice; @end @interface JSObject : NSObject<JSObjectProtocol> @end
在
JSObject.m
`文件://提示框hud 三方库 #import "MBProgressHUD.h" //APP屏幕视图 #define APP_SCREENWINDOW [UIApplication sharedApplication].delegate.window
//js调用了此处的iOS 原生方法 -(void)requestSaveTouch:(BOOL)isSuccess Event:(NSString *)notice { //保存 信息 dispatch_async(dispatch_get_main_queue(), ^{ if (isSuccess == YES) { //只显示文字 MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:APP_SCREENWINDOW animated:YES]; hud.mode = MBProgressHUDModeText; hud.label.text = notice?notice:@"保存成功!"; hud.margin = 10.f; hud.offset = CGPointMake(0, 0.f); hud.removeFromSuperViewOnHide = YES; [hud hideAnimated:YES afterDelay:1.5f]; hud.userInteractionEnabled = NO; } else { //只显示文字 MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:APP_SCREENWINDOW animated:YES]; hud.mode = MBProgressHUDModeText; hud.label.text = notice?notice:@"保存错误!"; hud.margin = 10.f; hud.offset = CGPointMake(0, 0.f); hud.removeFromSuperViewOnHide = YES; [hud hideAnimated:YES afterDelay:1.5f]; hud.userInteractionEnabled = NO; } }); } -(void)requestSubmitTouch:(BOOL)isSuccess Event:(NSString *)notice { //提交 信息 dispatch_async(dispatch_get_main_queue(), ^{ if (isSuccess == YES) { //只显示文字 MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:APP_SCREENWINDOW animated:YES]; hud.mode = MBProgressHUDModeText; hud.label.text = notice?notice:@"提交成功!"; hud.margin = 10.f; hud.offset = CGPointMake(0, 0.f); hud.removeFromSuperViewOnHide = YES; [hud hideAnimated:YES afterDelay:1.5f]; hud.userInteractionEnabled = NO; } else { //只显示文字 MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:APP_SCREENWINDOW animated:YES]; hud.mode = MBProgressHUDModeText; hud.label.text = notice?notice:@"提交错误!"; hud.label.numberOfLines = 0; hud.label.lineBreakMode = NSLineBreakByCharWrapping; //可能换行 hud.margin = 10.f; hud.offset = CGPointMake(0, 0.f); hud.removeFromSuperViewOnHide = YES; [hud hideAnimated:YES afterDelay:1.5f]; hud.userInteractionEnabled = NO; } }); }
使用:
头文件:
#import "JSObject.h"
- (void)webViewDidFinishLoad:(UIWebView *)webView{ // 初始化content self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]; //js交互 JSObject *JsObj = [JSObject new]; self.context[@"Android"] = JsObj; //key值 }
效果:
思想
OC方法:“
-(void)requestSubmitTouch:(BOOL)isSuccess Event:(NSString *)notice;//提交 信息
”
等价于
JS方法:“Android.requestSubmitTouchEvent(true,data.CodeMsg);
”的响应
OC方法:“-(void)requestSaveTouch:(BOOL)isSuccess Event:(NSString *)notice;//保存 信息
”
等价于
JS方法:“Android.requestSaveTouchEvent(true,data.CodeMsg);
”的响应
总结:书写时JSObject的方法,只要保证所传递的数据类型 相同、名字连起来 相同即可!!
安卓端java书写:
/** * 与js交互时用到的方法,在js里直接调用的 */ @JavascriptInterface public void requestSaveTouchEvent(boolean b,String a) { if(b){ doShowToast("保存成功"); isSave=true; }else { doShowToast(a); } } @JavascriptInterface public void requestSubmitTouchEvent(boolean b,String a) { if(b){ doShowToast("提交成功"); isSubmit=true; AfterClassReflectActivity.this.finish(); }else { doShowToast(a); } }
道理一样,以相应的函数 响应JavaScript的操作!
OC调用JS的函数:
执行JavaScript语句! 类比FMDB~
在“- (void)viewDidLoad { }
”里面:// 在界面上添加一个按钮,实现:OC端控制h5,实现弹出alert提示框 UIButton * alertBtn = [[UIButton alloc] initWithFrame:CGRectMake(100, 500, 100, 30)]; [alertBtn setTitle:@"按钮" forState:UIControlStateNormal]; alertBtn.backgroundColor = [UIColor redColor]; [alertBtn addTarget:self action:@selector(showHtml5Alert) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview: alertBtn];
//提示框alert 展示 - (void)showHtml5Alert { //要将script的alert()方法转化为string类型 NSString * alertJs=@"alert('Hello Word')"; //警告框 //alertJs=@"confirm('Hello Word')"; //确认框 //alertJs=@"prompt('Hello Word','123456')"; //提示框 + 文字输入框 [self.context evaluateScript:alertJs]; }
三方库(WebViewJavaScriptBridge)
使用步骤
- 1.创建WebView
- 2.创建WebViewJavaScriptBridge对象
- 3.注册JS要调用的Native
handlerName:需要调用的JS名字(无后缀)
handler:需要OC进行的操作
自己并没有熟练使用WebViewJavaScriptBridge三方库!公司的项目也只用了<JSExport>协议 就解决问题了!
以后熟练了WebViewJavaScriptBridge,再来补上吧!
可参考:WebViewJavascriptBridge-Obj-C和JavaScript互通消息的桥梁
很久就想写一下JavaScript的东西!😂😂😂
公司的项目里面使用到了,终于写了一篇!