Web 与 App 数据交互原理和实现

article/2025/11/4 22:12:08

作者 | 张小虎

杏仁前端开发工程师,前 iOS 开发工程师,关注前端技术栈。


背景

点击图片查看大图已经成了用户浏览页面时的一种习惯,原生 App 往往都实现了这些图片处理功能(点击查看、缩放、保存、滑动浏览等)。对于 Web 页面,为了更好的体验,一般开发者都会自己实现或是使用三方的图片处理框架。但如果一个 Web 页面能在一些特定的原生 App 中打开,那完全可以让 App 去代理处理这些图片。毕竟原生 App 的体验会更好,而且同一个 App 内点击原生图片和 Web 里面的图片,体验应该是一致的。

所以需求很简单,就是Web 页能直接调用原生的图片显示功能嘛!

交互原理

这个需求背后要解决的问题,实际上是要通过 Web 与原生的交互,让 Web 把图片资源交给原生应用去处理。

iOS7 之后苹果推出 JSCore,通过获取 Web 上下文环境,实现了 App 可以直接调用 JS 方法,或者将 block 赋值给 JS 方法来实现 Web 调用 App 并传值。所以在不考虑安卓的情况下,可以通过 JSCore 实现 Web 与 App 交互。

JSCore

App 端

// 获取JS上下文


JSContext *jsContext;

-(void)WebViewDidFinishLoad:(UIWebView *)webView {jsContext = [_webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
}

// App 调 Web insertText 事件
JSValue *funcValue = jsContext[@"insertText"];
[funcValue callWithArguments:@[@"hello web!"]];

// Web 调 App,App注册事件名为callNative
jsContext[@"callNative"] = ^(NSString*str){NSLog(str);
};


Web 端

// 接收 App 调用
function insertText(text) {...
}

// 调用 App
btnNode.onclick = () => {callNative('hello app!');
}

这种方式使用简单,但大多数情况需要兼容 iOS 与安卓,所以需要找到更合适的方式。

传统方式

苹果推出 JSCore 以前,App 调用 Web 只能通过 WebView 执行 JSString 来实现。而 Web 没法直接调用 App,只能触发特定链接,让 App 在 WebView 代理方法中捕获到这特定链接,从而执行相应操作,间接实现 Web 调 App。这种传统方式也适用于安卓端的的实现。

App 调用 Web

[_webView stringByEvaluatingJavaScriptFromString:jsString];

这里的 JSString 是一个 JS 方法的调用,这个方法能给 Web 传值的前提是在 Web 端定义一个全局方法如:

function handlerMessageFromApp(data) {...}

那 App 端需要去拼接出这个 JSString 然后再调用 Webview 的 stringByEvaluatingJavaScriptFromString 方法:

NSString* jsString = [NSString stringWithFormat:@"handlerMessageFromApp('%@');", messageJSON];


[_webView stringByEvaluatingJavaScriptFromString:jsString];

App 调用 Web 就是利用这种 Webview 去执行一个 JS 方法的方式去实现。JS 方法可以直接返回值给 App,但通常情况下 Web 端收到 App 的消息会去进行一些异步操作,这样在 handlerMessageFromApp 中直接返回就不太合适了。此时需要有另外一个流程去保证 Web 端把消息传递给 App,也就是下面会说的 Web 调 App。

Web 调用 App

Web 调 App 则需要双方事先沟通定好协议。比如如果要点击 Web 页面链接跳转到 App 主页,那可以将协议的名称定为 xr://home,HTML 内容为 <a href="xr://home">查看主页>></a>,点击链接就会发生 url 的改变,同时原生 WebView 的代理方法也会被触发。通过在代理方法中监听 url 的变化实现约定的协议。

// 在 webview 代理方法中处理


- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {NSURL *url = [request URL];if (url == "xr://home") {...}
}


如果基于这种方式让 Web 给 App 传值可以有两种方式:

  1. 直接在协议后面拼接参数如 xr://message?name=carson,这种方式适合于简单的值传递,但对于复杂结构的数据传递这种方式不合适。

  2. Web 端 与 App 端定好消息协议如:xr://message,Web 端要发送消息给 App 端时触发该协议,同时将要传递的值放在页面上,App 端监听到该协议变化时从 Web 页面上取值。这种方式适合传递复杂数据。


现实开发中的传值往往都是复杂结构的,所以我们选择第2种方式去完成 Web 端调用 App 端。

function getMessageFromWeb() {
 return messageObject;
}

基于前面的经验在 Web 端实现方法 getMessageFromWeb,这个方法负责返回要传递给 App 的值。

id messages = [_webView stringByEvaluatingJavaScriptFromString:@"getMessageFromWeb()"];

当特定的消息协议被触发时 App 通过 Webview 执行带有返回值的 JS 方法拿到数据,这就间接实现 Web 调用 App 并传值的原理。


但这种方式 Web 端每次调用时都需要触发特定协议,同时将全局变量 messageObject 赋值。我们往往希望有一个抽象层来做这些事情,每当调用的时候作为调用方最好是能一个方法传递消息名称与消息内容就行了,接收方也只需要按消息名称接收消息内容。Web 端与 App 端都应该具备这样一个抽象层,这样具体的两端交互就简化成了一端只管调用另一端只管接收。有了这样一个抽象层再来看 Web 端调 App 端就好比:


  1. W 委托 B 发消息给 A 说有包糖要给他,此时 W 已经把糖交给了 B。

  2. B 发出通知给 A。

  3. A 收到通知后跑过来从 B 这里拿走了糖。


这样一个单向的 W 把消息发送给 A 就完成了,原理还是基于前面 Web 调用 App 的原理。因为有 B 的存在此时 W 要做的事情少了很多。


完整的调用

上面的过程只是最简单的情况,是一个单向的,正常情况下 W 给 A 送了包糖或许还想知道 A 什么时候吃完,吃完了 W 可以再去买。


  1. W 委托 B 发消息给 A 说有包糖要给他,此时 W 已经把糖交给了 B。

  2. B 发出通知给 A。

  3. A 收到通知后跑过来从 B 这里拿走了糖。

  4. A 吃完糖后再通知到 B 说他吃完了。

  5. B 最后通知到 W,W 再去买糖。


步骤4与步骤5代表 App 回调 Web。W 最后再买糖相当于回调函数的实现,这是在 W 送糖的时候就已经决定的事情。 因为整个一去一回的过程并非同步,所以这个地方就需要处理好这样一个映射:消息 —> 回调处理函数。也就是说每条发送的消息对应上各自的回调处理函数,这就需要 B 去维护这样一个映射关系。B 给要发送的消息加上 callbackId,同时以 { callbackId: callbackHandler } 的方式将回调处理函数存储起来。A 收到了有 callbackId 的消息再响应时又回继续带上这个 callbackId,最后 B 按照 callbackId 找到回调处理函数去执行。这样才是一个完整的带有回调处理的 Web 调用 App 并传值。


所以关键任务是去实现 B 这样一个抽象层,B 的任务很重,它是一个 Web 端与 App 端交互的桥梁,它要具备发送消息提示、存储消息内容、存储消息回调、 接收消息、执行消息回调等功能。


实现这样一个抽象层并不算太难,但重复造轮子的事就不做了,前面描述的过程也正是参照第三方库 WebViewJavascriptBridge 的实现,B 也正是这个框架的核心 bridge,其整个实现基于观察者模式,在最基本的原理上加上了一些封装,抽象出一层 bridge 负责两端的交互,最终暴露给开发者的只有简单的 API(初始化、注册、调用)。

正如 bridge 这个名字一样,它起着桥梁作用,实现了两端的数据交互。这两个 bridge 基本实现了相同的功能,唯一的区别在于 Web 端这边的 bridge 没法直接发送消息内容,只能告诉 App 端有消息。

应用

回到最开始的需求,还是在 WebViewJavascriptBridge 的基础上去实现让 App 去处理 Web 里的图片。做过图片浏览的应该都知道,实现图片浏览需要提供所有图片的数组 array 以及当前点击图片的 index。所以给 img 标签绑定点击事件,再获取所有图片的数组,最后利用 JSBridge 传给 App 即可。至于第三方库的接入可以去查看官方文档。


App 端注册 handler,用于处理接收图片:

[self.bridge registerHandler:@"previewImage" handler:^(id data, WVJBResponseCallback responseCallback) {
 // 处理图片 data
}]

相应的 Web 端要去 callHandler:

// setup 去触发 App 将 bridge 注入 window
setupWebViewJavascriptBridge(function(bridge) { bridge.callHandler('previewImage', { urls: [ /* ... */ ], index: 0 });
}

就这么简单的一端管接收另一端管调用就完成了 Web 将图片传给原生。

熟悉微信网页开发的应该知道微信也提供了相关功能,微信中的网页可以利用微信的 JSSDK 使用原生提供的一整套图片处理功能:相册、相机、裁剪、上传、下载、图片浏览...



App 与 Web 交互的场景还有很多,比如 Web 页自定义分享、控制 App 页面跳转,随着小程序的出现 Web 端与 App 的交互也是更加有了深度。总之原理不难,掌握了原理才能做出更好更多的事情。



全文完



以下文章您可能也会感兴趣:

  • 乐高式微服务化改造(上)

  • 乐高式微服务化改造(下)

  • 一个创业公司的容器化之路(一) - 容器化之前

  • 一个创业公司的容器化之路(二) - 容器化

  • 一个创业公司的容器化之路(三) - 容器即未来

  • 四维阅读法 - 我的高效学习“秘技”

  • 工程师成长的必备技能

  • iOS 屏幕适配浅谈


我们正在招聘 Java 工程师,欢迎有兴趣的同学投递简历到 rd-hr@xingren.com 。


杏仁技术站


长按左侧二维码关注我们,这里有一群热血青年期待着与您相会。







http://chatgpt.dhexx.cn/article/qvcWyMcT.shtml

相关文章

人机交互-8-交互式系统设计

1. 设计框架 过早地把重点放在小细节、小部件和精细的交互上会妨碍产品的设计 先站在一个高层次上关注用户界面和相关行为的整体结构房屋设计举例 设计框架 定义高层次上的屏幕布局定义产品的工作流、行为和组织 1.1. 定义外形因素和输入方法 外形因素 设计什么样的产品&am…

人机交互-2-交互设计的原则与方法

交互设计的原则与方法 交互设计中的问题 尽量减少用户需要记忆的部分缺乏反馈 1. 目标Goal vs. 意图Intention 单个目标可对应多个意图 举例:删除文档中的部分内容的目标意图1:通过编辑菜单删除意图2:通过删除按钮删除每个意图可包含一系列活动 2. EEC模型 从用户视角探…

网页交互性设计

对于任何一个Web应用&#xff0c;与用户互动是最基本的要求。为Web应用增加交互性&#xff0c;最常用的方法&#xff0c;莫过于使用 Javascript 或 jQuery、AJAX 了。 本节不打算详细介绍这几种技术&#xff0c;只是简要介绍在网页版 word 中&#xff0c;如何使用这些技术来实…

web与服务器之间的信息交互,web客户端与服务器端如何进行交互

web客户端与服务器端如何进行交互 内容精选 换一换 开启了 Kerberos认证的安全模式集群,进行应用开发时需要进行安全认证。Kerberos这一名词来源于希腊神话“三个头的狗——地狱之门守护者”,后来沿用作为安全认证的概念,使用Kerberos的系统在设计上采用“客户端/服务器”结…

网易交互设计师微专业C5 交互设计测试与评估

如果有需要视频资源的可以关注"AI产品经理人"&#xff0c;回复关键字“网易交互设计微专业”获取下载链接~ Chapter5 交互设计测试与评估 第一章 为什么要开展测试与评估 用户测试&#xff1a;请目标用户使用产品来完成任务&#xff0c;观察并记录用户使用产品的…

网易交互设计师微专业C3 规范信息架构与流程设计

如果有需要视频资源的可以关注"AI产品经理人"&#xff0c;回复关键字“网易交互设计微专业”获取下载链接~ Chapter3 规范信息架构与流程设计 第一章 信息架构设计 &#xff08;一&#xff09;认知产品信息架构 定义&#xff1a; 信息架构设计是对信息进行结构…

【人机交互技术】Web界面设计

一、实验目的和要求 1&#xff09;熟悉 Web 站点的信息交互模型和结构 2&#xff09;熟悉 Web 界面设计的基本思想和原则 3&#xff09;掌握 Web 界面设计的工具和技术 二、实验内容与步骤 1&#xff09;实验内容: 要求根据 Web 界面设计的原则(简洁、一致性、对比度)&#…

尼尔森十大交互设计原则

前言 Jakob Nielsen&#xff08;雅各布尼尔森&#xff09;的十大交互设计原则。它们被称为“启发式”&#xff0c;因为它们是广泛的经验法则&#xff0c;而不是特定的可用性指导原则。因此&#xff0c;我们不能把它上升为一种标准&#xff0c;而是应该当做一种经验来学习&#…

人机交互-任务4:图形交互界面的设计(web)

文章目录 一、 题目二、 实验内容三、 方案设计四、 实验步骤与过程五、 实验结果与分析完整项目成品下载 一、 题目 目的 (1) 使用掌握的计算机语言完成图形界面的设计&#xff0c;熟悉图形用户界面设计的原则并运用到设计中。 (2) 通过用户友好界面的设计&#xff0c;使学生…

web交互设计模型

《信息架构中的常见模型》是整个“web交互设计方法”中的一部分&#xff1a; 本期的内容目的是分享和总结信息架构中一部分基本的交互模型。信息架构需要考虑内容和功能的建构,首先需要考虑怎样组织内容和功能的关系&#xff0c;也就是切 分内容&#xff0c;如何把一些动作和对…

交互设计文档示例_Web交互的重要性:提示和示例

网站创建涉及许多要素。 网站是与来自世界各地的用户进行交流的最佳媒介。 因此&#xff0c;至关重要的是&#xff0c;其设计方式应吸引用户并吸引其参与。 这是网站可以有效地覆盖其用户的时间。 设计师经常想知道使网站吸引人的秘密成分 。 设计和功能的结合是每个设计师都希…

计算机教改论文发在那家核心期刊,教改论文可以发表在哪些刊物上合适?

原标题&#xff1a;教改论文可以发表在哪些刊物上合适&#xff1f; 教师发表教改论文在考虑发表要求之余&#xff0c;都是希望自己的文章尽快见刊的&#xff0c;如果教师面临的是发表核心刊物的要求&#xff0c;那就做好一定的心理准备了&#xff0c;核心期刊没有容易发表的&am…

刊物论文级别

公开发表的论文分为六个级别是什么 &#xff1f; (2014-04-18 15:35:20) 转载▼ 第一级&#xff0d;T类 特种刊物论文&#xff0c;指在《SCIENCE》和《NATURE》两本期刊上发表的论文。 第二级&#xff0d;A类&#xff1a;权威核心刊物论文&#xff0c;指被国际通用的SCIE、EI…

计算机专业发论文的等级有哪些,计算机专业发表职称论文多少字

计算机专业发表职称论文多少字?文章的字数关系着作者的发表费用多少&#xff0c;字数越多&#xff0c;作者的费用负担就要越重&#xff0c;所以&#xff0c;广大作者一定充分把握字数的要求&#xff0c;以免写得字数过多或是过短&#xff0c;这样都是不容易发表的&#xff0c;…

计算机论文刊物发表,计算机论文发表流程

一、计算机论文发表流程&#xff1a; 1、根据当地评审需求选定刊物&#xff0c;确定出刊时间及费用。 2、您将论文发给我们&#xff0c; 看看是否符合杂志社要求。 3、将定金40%付到支付宝担保交易&#xff0c;安排给杂志社审稿 4、审稿通过后您将收到杂志社出的用刊通知书。打…

Python散点图拟合

散点图拟合 import matplotlib.pyplot as plt import numpy as npx [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] y np.array([5760, 3600, 1620, 1260, 1080, 900, 1080, 1800, 3060, 4680, 2880, 5040, 4140, 5580, 5040, 4…

用python绘制二维数据的散点图

用python绘制二维数据的散点图 一 绘制散点图脚本 import matplotlib.pyplot as plt #需要安装该 matplotlib库 import pandas as pd #需要安装pandas库#读入文件 file_path "data.txt"#存放二维数据的txt文件&#xff0c;换成自己的路径下 df pd.read_table(fil…

【matplotlib】散点图详解

目录 引用s 点的大小c 点的颜色 & cmap 配色方案marker 标号 & s 点的大小alpha 标号透明度linewidths 标号边缘的宽度edgecolors 标号边缘的颜色散点图大概长这样: 引用 调用方式:matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, norm…

图文并茂的Python散点图教程

看完本教程&#xff0c;就可以应付大多数情况下的柱状图绘制了。 声明&#xff1a; 需要读者了解一点Python列表的知识教程借助于matplotlib库 散点图基础 必要的库 # 需导入要用到的库文件 import numpy as np # 数组相关的库 import matplotlib.pyplot as plt # 绘图库…