js|小程序和h5通信

一、关于jsBridge 1、说起h5通信,一个绕不开的话题就是jsBridge,什么是jsBridge? 随着HTML5兴起,其独特的新特性,完全能够满足app开发需求,并且,相比于原生更容易入门,缩短开发周期,现在很少有纯原生的APP。但是,由于H5页面是内嵌到原生应用的WebView组件(一个浏览器内核)中,而手机浏览器Javascript引擎是在一个沙箱环境中运行,因此JavaScript的权限受到严格限制,不能够操作系统功能,我们常常在react项目中使用相机功能,需要使用桥接代码,不能直接去操作原生的api,所以,如果JavaScript要用到这些受限的能力时,就需要委托原生去实现,原生完成后,再将结果通知JavaScript,因此,JavaScript和原生之间就需要一个通信的桥梁,而这个桥梁本质上就是原生的浏览器组件(我们统一称之为WebView)与Javascript 通信的通道,一般称为 WebView JavaScript Bridge, 为了简单,一般简称为 JS bridge。
2、JS 调用 Native JS 调用 Native 的实现方式较多,主要有拦截 URL Scheme (钉钉小程序路由跳转支持)、重写 prompt 、注入 API 等方法。
然而,上述方法都是native内部做了集成,有相应的处理函数用来做出处理。然而,小程序内部并没有这些集成方法,因此,都不太适用于小程序。
微信小程序有一句话:“ web-view 网页与小程序之间不支持除 JSSDK 提供的接口之外的通信 ”,也就是小程序通信必须使用小程序自己提供的JSSDK,不支持,其他任何通信方式。
二、js之间通信

  • 上边介绍了js和非js之间的通信(jsBridge),那么,js(小程序)和js(h5)之间如何通信呢?
还记得我关于谷歌浏览器插件技术分享吗?谷歌浏览器插件后台js和当前页面通信是通过chrome.runtime完成消息传递(sendMessage)。
  • 能使用window上的postMessage来传递信息吗?
答案显然不能,微信小程序也好,钉钉小程序也好,都对window进行了代理,h5的window和小程序window,不再是同一个window,这中间还存在着某些差异,因此,不能直接使用。
  • h5和小程序有哪些隔阂?
由于h5是通过web-view内嵌在小程序中,因此,使用状态管理方式有可能就是不一样的,比如,有些使用redux,有些使用mobox,有些使用dvajs,有些使用react.Context。由于域名也可能是不同的,因此,公用localStorage和sessionStorage来共享数据也是不可取的。因此,需要中间一个桥梁来传递参数来共享数据。好在,各个小程序平台,设计时候都考虑到了这一点,可以借助各个平台提供的postMessage来实现双向通信。
三、各个平台消息传递汇总(rax语法) 1、钉钉小程序(阿里小程序) (1)、小程序向h5发送消息
  • 小程序端
注意: dd.createWebViewContext里参数必须设置为Embed的id,否则将会失效
import { createElement, useEffect, useState } from 'rax'; import View from 'rax-view'; import styles from './index.module.scss'; import Embed from 'rax-embed'; function WebView({ src = 'http://127.0.0.1/index.html' }) {const [content, setContent] = useState(null); useEffect(() => { const contentWeb = dd.createWebViewContext('web-view-page'); setContent(contentWeb); }, []); function handleSendMessage() { content.postMessage({ items: '20', age: '490859' }); } return ( handleSendMessage()} style={{ height: '100%', width: '100%', }} /> ); }export default WebView;

  • h5端
使用前先向h5端引入钉钉web-view包。
type="text/javascript" src="https://appx/web-view.min.js"> // 如该H5页面需要同时在非钉钉客户端内使用,为避免该请求404,可参考以下写法 // 请尽量在html头部执行以下脚本 > if (navigator.userAgent.toLowerCase().indexOf('dingtalk') > -1) { document.writeln('+ '>' + '<' + '/' + 'script>'); }// 接收来自小程序的消息。 dd.onMessage = function(e) { console.log(e); //{'sendToWebView': '1'} }

(2)、h5向钉钉发送消息
  • h5端
【js|小程序和h5通信】dd.postMessage({name:“测试web-view”}); 可以在具体某个页面使用,如果,需要统一拦截,可以在app.js入口文件进行修改逻辑。
type="text/javascript" src="https://appx/web-view.min.js"> // 如该H5页面需要同时在非钉钉客户端内使用,为避免该请求404,可参考以下写法 // 请尽量在html头部执行以下脚本 > if (navigator.userAgent.toLowerCase().indexOf('dingtalk') > -1) { document.writeln('+ '>' + '<' + '/' + 'script>'); } // 网页向小程序 postMessage 消息 dd.postMessage({name:"测试web-view"});

  • 小程序端(rax)
import { createElement, useEffect, useState } from 'rax'; import View from 'rax-view'; import styles from './index.module.scss'; import Embed from 'rax-embed'; function WebView({ src = 'http://127.0.0.1:9002/demo/index.html' }) {function handleMessage(message) { console.log(message, 'message', message.detail); } return ( ); }export default WebView;

2、微信小程序 微信小程序h5向小程序发送消息,需要借助wx.miniProgram.postMessage 的JSSDK 1.3.2 向小程序发送消息,会在特定时机(小程序后退、组件销毁、分享)触发组件的 message 事件,执行onMessage事件。因此,必须执行跳转后,才能传递参数。
(1)、h5向小程序传参
  • h5端
//引入wx插件 type="text/javascript" src="http://img.readke.com/220728/0RHGV3-2.jpg"> //返回小程序带参 type="text/javascript"> wx.miniProgram.getEnv(function(res) { if(res.miniprogram) { wx.miniProgram.switchTab({ url: '/pages/index/index' }); wx.miniProgram.postMessage({ data: { name: name, passwords :passwords } }); // 传的参数 } });

由于微信sdk需要路由跳转时候才能发送消息,因此,有些场景使用不了,可以借助uni的SDK 来实现。更多端兼容配置可以参考uni官网web-view
src="http://img.readke.com/220728/0RHG326-3.jpg"> type="text/javascript" src="http://img.readke.com/220728/0RHH216-4.jpg"> > document.addEventListener('UniAppJSBridgeReady', function() { uni.postMessage({ data: { action: 'message' } }); });

  • 小程序端
import { createElement, useEffect, useState } from 'rax'; import View from 'rax-view'; import styles from './index.module.scss'; import Embed from 'rax-embed'; function WebView({ src = 'http://127.0.0.1:9002/demo/index.html' }) {function handleMessage(message) { console.log(message, 'message', message.detail); } return ( ); }export default WebView;

(2)、小程序向h5传参 微信小程序不支持postMessage消息到h5端。可以通过url传参,注意,token和中文需要加密传输。

    推荐阅读