小程序和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 (
    <View className={styles['web-view']}>
      <Embed
        src={src}
        id="web-view-page"
        onLoad={() => handleSendMessage()}
        style={{
          height: '100%',
          width: '100%',
        }}
      />
    </View>
  );
}

export default WebView;
  • h5端

使用前先向h5端引入钉钉web-view包。

<script type="text/javascript" src="https://appx/web-view.min.js"></script>
// 如该H5页面需要同时在非钉钉客户端内使用,为避免该请求404,可参考以下写法
// 请尽量在html头部执行以下脚本
<script>
  if (navigator.userAgent.toLowerCase().indexOf('dingtalk') > -1) {
        document.writeln('<script src="https://appx/web-view.min.js"' + '>' + '<' + '/' + 'script>');
      }

    // 接收来自小程序的消息。
    dd.onMessage = function(e) {
      console.log(e); //{'sendToWebView': '1'}
    }
</script>
(2)、h5向钉钉发送消息
  • h5端

dd.postMessage({name:“测试web-view”});可以在具体某个页面使用,如果,需要统一拦截,可以在app.js入口文件进行修改逻辑。

<!-- html -->
<script type="text/javascript" src="https://appx/web-view.min.js"></script>
// 如该H5页面需要同时在非钉钉客户端内使用,为避免该请求404,可参考以下写法
// 请尽量在html头部执行以下脚本
<script>
  if (navigator.userAgent.toLowerCase().indexOf('dingtalk') > -1) {
        document.writeln('<script src="https://appx/web-view.min.js"' + '>' + '<' + '/' + 'script>');
      }
    // 网页向小程序 postMessage 消息
    dd.postMessage({name:"测试web-view"});
</script>
  • 小程序端(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 (
    <View className={styles['web-view']}>
      <Embed
        src={src}
        onMessage={handleMessage}
        style={{
          height: '100%',
          width: '100%',
        }}
      />
    </View>
  );
}

export default WebView;
2、微信小程序

微信小程序h5向小程序发送消息,需要借助wx.miniProgram.postMessage 的JSSDK 1.3.2 向小程序发送消息,会在特定时机(小程序后退、组件销毁、分享)触发组件的 message 事件,执行onMessage事件。因此,必须执行跳转后,才能传递参数。

(1)、h5向小程序传参
  • h5端
//引入wx插件
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
//返回小程序带参
<script 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
                }
            }); // 传的参数
        }
    });
</script>

由于微信sdk需要路由跳转时候才能发送消息,因此,有些场景使用不了,可以借助uni的SDK 来实现。更多端兼容配置可以参考uni官网web-view

<!DOCTYPE html>
<html lang="en">
  <!-- wx和uni的SDK -->  
  <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
  <script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.3/index.js"></script>
  <script>  
    document.addEventListener('UniAppJSBridgeReady', function() {  
      uni.postMessage({
            data: {
                action: 'message'
            }
        });
    });  
  </script>
</html>
  • 小程序端
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 (
    <View className={styles['web-view']}>
      <Embed
        src={src}
        onMessage={handleMessage}
        style={{
          height: '100%',
          width: '100%',
        }}
      />
    </View>
  );
}

export default WebView;
(2)、小程序向h5传参

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值