h5页面如何与原生交互

这篇具有很好参考价值的文章主要介绍了h5页面如何与原生交互。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文讲述h5页面跟原生通信,比如在app内,调用相机,获取相册内的图片,在app内拉起微信小程序等等,h5页面没有这么多权限能够直接调用移动端的原生能力,这个时候就需要与原生进行通讯,传递一个信号给原生这边,然后原生直接调用手机端的能力。

下面分别讲解h5与Android,ios系统通信

JS与Android

Android处理

其实h5能够在app内中存在,就是在app中有webview的存在,在webview中可以是一个h5的链接,这样这个h5页面就能够app内展现。

Android中,往webview里面注入WebViewJavascriptBridge.js

h5页面如何与原生交互,前端,前后端交互,分享,交互

我们能够看到在android往webview注入了一段js代码,接下来我们看看这段代码的逻辑。

h5页面如何与原生交互,前端,前后端交互,分享,交互

这里往webview中的document注入事件webViewJavascriptBridgeReady,向window中添加一个对象WebViewJavascriptBridge。

注意这个WebViewJavascriptBridge对象中包含了init,send,registerHandler,callHandler,_handleMessageFormNative函数。

接下来看这个init函数中的逻辑

h5页面如何与原生交互,前端,前后端交互,分享,交互

使用 iframe 创建消息队列的主要原因是:

  1. 实现跨域通信。iframe 可以被嵌入到不同域的页面中,使得父子页面可以跨域通信。
  2. 解耦通信方。使用 iframe,可以使得父页面和子页面的 JavaScript 环境相互隔离。父页面无法直接访问子页面的变量和函数,只能通过消息通信。这减少了两端的依赖,有利于后期维护。
  3. 兼容性好。iframe 比较老的技术,广泛支持各种浏览器,不需要担心兼容性问题。
  4. 简单易用。向 iframe 发送消息和监听消息非常简单,不需要额外的库或工具。

h5页面如何与原生交互,前端,前后端交互,分享,交互

这里可以发现,初始化就完成了创建消息队列,初始化默认消息队列,还有最重要的发送消息。

接下来就看h5怎么接收和处理这些通信了。

h5页面处理

到这里,应该也能猜到一些了,因为上面Android注入了一段js代码,从中创建了webViewJavascriptBridgeReady事件,而且往window中添加了一个对象。

那h5这边初始化也很简单,就是判断有没有window.WebViewJavascriptBridge,有的话,就直接可以传输了,没有的话,就需要监听webViewJavascriptBridgeReady事件,当这个事件执行了,就可以进行通信了。


    if (window.WebViewJavascriptBridge) {
        //do your work here
    } else {
        document.addEventListener(
            'WebViewJavascriptBridgeReady'
            , function() {
                //do your work here
            },
            false
        );
    }

而这个window.WebViewJavascriptBridge也就是常说的通讯桥。无论是h5调用原生方法,还是原生想要触发h5方法,都是需要使用到通讯桥。

如果未定义 window.WebViewJavascriptBridge ,则将所有 JsBridge 函数调用放入 window.WVJBCallbacks 数组中,当触发 WebViewJavascriptBridgeReady 事件时,此任务队列将被刷新。

function setupWebViewJavascriptBridge(callback) {
    if (window.WebViewJavascriptBridge) {
    return callback(WebViewJavascriptBridge);
}
    if (window.WVJBCallbacks) {
    return window.WVJBCallbacks.push(callback);
}
    window.WVJBCallbacks = [callback];
}

调用 setupWebViewJavascriptBridge ,然后使用桥注册处理程序或调用 Java 处理程序:

这里的registerHandler和callHandler应该很熟悉,因为在Android中注入的js代码中就有的这两个方法,这两个方法就在window.WebViewJavascriptBridge对象上。

setupWebViewJavascriptBridge(function(bridge) {
    bridge.registerHandler('JS to Android', function(data, responseCallback) {
        console.log("Android received response:", data);
        responseCallback(data);
    });
    bridge.callHandler('Android to JS', {'key':'value'}, function(responseData) {
           console.log("JS received response:", responseData);
    });
});

registerHandler方法是h5页面传递给Android的数据

callHandler方法是Android传递给h5的数据

总结一下工作流程:

  • JS端判断是否有window.WebViewJavascriptBridge对象;
  • 有的话就进入回调,进行通信;
  • 没有的话就需要, 将所有 JsBridge 函数调用放入 window.WVJBCallbacks 数组中,当触发 WebViewJavascriptBridgeReady 事件时,此任务队列将被刷新;

JS与IOS

IOS处理

在ios处理中,需要介绍一下WebViewJavascriptBridge

h5页面如何与原生交互,前端,前后端交互,分享,交互

WebViewJavascriptBridge 是用于在 WKWebView,UIWebView 和 WebView 中的 Obj-C 和 JavaScript 之间发送消息的 iOS / OSX 桥接器。

这里本质跟Android是一样的,也是注入了一段js代码,然后注入到webview组件中,实现原生与js的交互。

h5页面如何与原生交互,前端,前后端交互,分享,交互

我们先看看js处理的逻辑

h5页面如何与原生交互,前端,前后端交互,分享,交互

这里跟Android还是很像,往window中注入一个通讯桥,通讯桥的名称是WebViewJavascriptBridge,然后在通信桥上有registerHandler,callHandler,disableJavscriptAlertBoxSafetyTimeout,_fetchQueue,_handleMessageFromObjC等方法。

接下来看一下如何往webview中注入的

h5页面如何与原生交互,前端,前后端交互,分享,交互

与上面的Android不同的是,这是ObjC语言编写的,Android是Java语言。

// WKNavigationDelegate 协议方法,用于监听 Request 并决定是否允许导航
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    // webView 校验
    if (webView != _webView) { return; }
    NSURL *url = navigationAction.request.URL;
    __strong typeof(_webViewDelegate) strongDelegate = _webViewDelegate;

    // 核心代码
    if ([_base isWebViewJavascriptBridgeURL:url]) { // 判定 WebViewJavascriptBridgeURL
        if ([_base isBridgeLoadedURL:url]) { // 判定 BridgeLoadedURL
            // 注入 JS 代码
            [_base injectJavascriptFile];
        } else if ([_base isQueueMessageURL:url]) { // 判定 QueueMessageURL
            // 刷新消息队列
            [self WKFlushMessageQueue];
        } else {
            // 记录未知 bridge msg 日志
            [_base logUnkownMessage:url];
        }
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    
    // 调用 _webViewDelegate 对应的代理方法
    if (strongDelegate && [strongDelegate respondsToSelector:@selector(webView:decidePolicyForNavigationAction:decisionHandler:)]) {
        [_webViewDelegate webView:webView decidePolicyForNavigationAction:navigationAction decisionHandler:decisionHandler];
    } else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}

h5页面处理

这里跟Android处理不同,启动通讯桥时,在h5页面也需要创建一个iframe标签来进行通信

function setupWebViewJavascriptBridge(callback) {
	if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
	if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
	window.WVJBCallbacks = [callback];
	// 创建一个 iframe
	var WVJBIframe = document.createElement('iframe');
	// 设置 iframe 为不显示
	WVJBIframe.style.display = 'none';
	// 将 iframe 的 src 置为 'https://__bridge_loaded__'
	WVJBIframe.src = 'https://__bridge_loaded__';
	// 将 iframe 加入到 document.documentElement
	document.documentElement.appendChild(WVJBIframe);
	setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
}

Note: 假 Request 的发起有两种方式,-1:location.href -2:iframe。通过 location.href 有个问题,就是如果 JS 多次调用原生的方法也就是 location.href 的值多次变化,Native 端只能接受到最后一次请求,前面的请求会被忽略掉,所以这里 WebViewJavascriptBridge 选择使用 iframe。

因为加入了 src 为 https://__bridge_loaded__ 的 iframe 元素,我们上面截获 url 的代理方法就会拿到一个 https://__bridge_loaded__ 的 url,由于 https 满足判定 WebViewJavascriptBridgeURL,将会进入核心代码区域接着会被判定为 BridgeLoadedURL 执行注入 JS 代码的方法,即 [_base injectJavascriptFile];

这样就形成了初始化桥,与android中的将所有 JsBridge 函数调用放入 window.WVJBCallbacks 数组中,后面要处理的逻辑一样了。

- (void)injectJavascriptFile {
    // 获取到 WebViewJavascriptBridge_JS 的代码
    NSString *js = WebViewJavascriptBridge_js();
    // 将获取到的 js 通过代理方法注入到当前绑定的 WebView 组件
    [self _evaluateJavascript:js];
    // 如果当前已有消息队列则遍历并分发消息,之后清空消息队列
    if (self.startupMessageQueue) {
        NSArray* queue = self.startupMessageQueue;
        self.startupMessageQueue = nil;
        for (id queuedMessage in queue) {
            [self _dispatchMessage:queuedMessage];
        }
    }
}

最后,调用 setupWebViewJavascriptBridge ,然后使用桥注册处理程序并调用 ObjC 处理程序:

setupWebViewJavascriptBridge(function(bridge) {
	
    /* Initialize your app here */

    bridge.registerHandler('JS to IOS', function(data, responseCallback) {
        console.log("IOS received response:", data)
        responseCallback(data)
    })
    bridge.callHandler('IOS to JS', {'key':'value'}, function responseCallback(responseData) {
           console.log("JS received response:", responseData)
    })
})

最后总结一下WebViewJavascriptBridge 的工作流:

  • JS 端加入 src 为 https://__bridge_loaded__ 的 iframe
  • Native 端检测到 Request,检测如果是 __bridge_loaded__ 则通过当前的 WebView 组件注入 WebViewJavascriptBridge_JS 代码
  • 注入代码成功之后会加入一个 messagingIframe,其 src 为 https://__wvjb_queue_message__
  • 之后不论是 Native 端还是 JS 端都可以通过 registerHandler 方法注册一个两端约定好的 HandlerName 的处理,也都可以通过 callHandler 方法通过约定好的 HandlerName 调用另一端的处理(两端处理消息的实现逻辑对称)

看到这里,其实Android和IOS系统最大的不同,相信大家已经感受到了,那就处理流程顺序不太一样。

但其实在公司的项目里面,上面这些知识只是基础,而公司内,都会制定一套完整的sdk来,各个端对齐,而sdk中,也不是简单的通信,还会有各种兼容,比如当前运行的系统,是否在指定的app内,app的版本信息,各个通信函数是否支持最低的版本号…

如果需要封装自己项目中的webview组件,还需要另外实现HTTP cookie注入,自定义User-Agent,白名单或者权限校验等等功能,更进一步还需要对webview组件进行初始化速度,页面渲染速度以及页面缓存策略的优化。文章来源地址https://www.toymoban.com/news/detail-586633.html

到了这里,关于h5页面如何与原生交互的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 移动端 h5和原生交互的方式

    一、h5传递给原生WebView的数据协议 传递的是个json字符串: id:这次操作的id,回调时会再传回来。因为交互有可能是异步的,对同一个接口调用多次时,回调时以id来区分是哪一次。id由js自己定义保证唯一即可,简单的做法是使用Math.random() action:操作名称,取名应该能反映

    2024年01月25日
    浏览(47)
  • H5端和原生APP进行交互

    浅浅记录一下吧!!! H5端和原生APP(安卓、IOS)进行数据交互 H5调用APP事件方法: 这里的  fn  是和APP开发人员协商好的方法名,APP端写逻辑代码,H5端直接调用APP的方法; ()里面可以向APP端传递数据,如果是引用数据类型的话,建议转成字符串再传递。 APP调用H5端事件方法:

    2024年02月22日
    浏览(44)
  • h5页面和app进行交互

    一、react native开发的 1.h5向app发送消息,app 接收并操作 2.app操作完成,向h5 返回消息,h5监听并处理   二、原生app 1.h5使用app方法: 2.app使用h5方法  

    2024年02月13日
    浏览(56)
  • 【前后端数据交互】原生JS的Fetch请求封装

    1.1 AJAX 概述 AJAX 是最早出现请求数据的方式,它不需要不需要刷新整个页面即可更新部分数据。 属于原生 JS 范畴 ,技术核心是 XMLHttpRequest 对象。 AJAX 请求过程:创建 XMLHttpRequest 对象、连接服务器、发送请求、接收响应数据 一般使用之前,我们都需要把它们封装使用,如下

    2024年02月15日
    浏览(35)
  • uniapp生成的h5与flutter的原生进行交互

            最近拿到需求是要配合app做一些h5的页面,刚好h5又是用uniapp生成的,使用起来跟普通的h5有些区别,所以在这里总结一下使用uniapp生成的h5页面如何跟flutter进行数据的传递 这里的 kjToLessonSubmit 是flutter那边写好的方法 这里值得注意的是,我们使用uniapp去书写代码的

    2024年02月11日
    浏览(51)
  • H5分享h5页面、小程序到微信

    先去微信公众平台填写js接口安全域名 本来想用微信开发js-sdk的,但是做了半天好像没啥效果 概述 | 微信开放文档 (qq.com) 引入js文件:http://res.wx.qq.com/open/js/jweixin-1.6.0.js  代码部分: 单独的h5是唤不起微信的,需要原生app去集成微信的sdk,app去调微信的方法,h5再去调app的方

    2024年02月09日
    浏览(43)
  • h5页面调用小程序分享方法

    小程序端 H5端

    2024年02月03日
    浏览(42)
  • ERP进销存源码PHP可生成H5页面和APP-前后端全开源

    企业资源规划 (ERP)是指组织用来管理日常业务活动(例如会计、采购、项目管理、风险管理和合规性以及供应链运营)的软件。完整的 ERP 套件还包括企业绩效管理、帮助计划、预算、预测和报告组织财务结果的软件。ERP系统将众多业务流程联系在一起,并实现它们之间的数

    2024年01月18日
    浏览(30)
  • Vue.js uni-app 混合模式原生App webview与H5的交互

    在现代移动应用开发中,原生App与H5页面之间的交互已经成为一个常见的需求。本文将介绍如何在Vue.js框架中实现原生App与H5页面之间的数据传递和方法调用。我们将通过一个简单的示例来展示如何实现这一功能。 效果图如下: 首先,我们需要在Vue.js项目中引入原生App与H5页面

    2024年02月16日
    浏览(69)
  • JSBridge原理 - 前端H5与客户端Native交互

    在混合应用开发中,一种常见且成熟的技术方案是将原生应用与 WebView 结合,使得复杂的业务逻辑可以通过网页技术实现。实现这种类型的混合应用时,就需要解决H5与Native之间的双向通信。JSBridge 是一种在混合应用中实现 Web 和原生代码之间通信的重要机制。 1.1. 混和开发:

    2024年04月12日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包