微信小程序发送消息到web-view

Send message from WeChat mini-program to web-view

我正在构建微信小程序,其中一个页面具有 web-view 控件。例如:

page.wxml

<web-view src="https://..." bindmessage="onWebViewMessage"></web-view>

page.js

const app = getApp();
Page({
    onWebViewMessage:function(e) {
         console.log(e);
    },
    onLoad:function() {
    }
});

web-view中加载了一个HTML页面(index.html),其中包括来自微信的jweixin-1.3.2.js库,用于连接微信API如连接父小程序。页面为空,没有 DOM 个元素,只有 javascript 将在加载文档时执行。

它 javascript 是这样的:

index.js

document.addEventListener('DOMContentLoaded',function(){
    wx.miniProgram.postMessage({data:'test'});
});

我能够 post 从这个文档到小程序的消息没有问题。也可以发送一些小程序导航指令,比如wx.miniProgram.navigateTo({url:'path/to/page'}); 这样看起来一切都很好。我也可以在web-view加载完成后在小程序中得到回调

问题:

如何从小程序post发送消息到网页浏览?例如,将字符串或对象传递给网络视图。

我在谷歌上搜索了几个小时,似乎找不到任何人在做这件事,但我不敢相信这只是一种可能的单向交流。

感谢任何帮助或想法!

我找到了一种将数据从 mini-program 传递到 web-view 内容的有效方法,目前看来,这是唯一可行的方法。

Mini-program

1。 Base64 模块

您需要能够将普通字符串转换为 Base64 字符串。 Mini-program API 有一种将字节数组转换为 base64 字符串的方法,但不能用于此目的。因此,创建您自己的模块来执行此操作:

文件:lib/b64.js

var string2base64 = function(str) {
    .... here put your js code for making b64 string ....
    return result;
};

module.exports = {
    string2base64
};

2。 Web-View

页面

在有 web-view 控件的页面中,像这样在 wxml 文件中准备 DOM 元素:

文件:pages/xxx/index.wxml

<web-view src="{{webURL}}" bindload="onWebLoad" binderror="onWebError"></web-view>

请注意 src 参数现在绑定到页面的 webURL 属性。每当页面为此 属性 设置值时,将自动应用于 DOM 元素。

在文件 pages/xxx/index.js 中,您需要添加 base64 模块:

const b64 = require('../../lib/b64.js')

请注意,需要的路径可能因您设置项目的方式而异

并在页面的 data 对象中,添加 webURLwebBaseURL 属性,如下所示:

Page({
    data: {
        webURL:'',
        webBaseURL:'https://your/web/app/url',
        messageQueue:[],
        messageQueueSize:0,
        .... other page properties go here ....
    },
    ..... rest of your page code goes here .....
})

注意 webURL 设置为空。这意味着当页面加载时,空字符串将默认设置为 DOM 对象。

webBaseURL稍后会解释。

messageQueue 是一个数组,它将存储要发送到 web-view 的未决消息。 messageQueueSize 只是数组长度。用于更好的性能,避免读取 Array.length.

3。启动消息队列

在页面的onShow回调中,设置webURL并开始每250ms读取messageQueue数组的间隔。如果你不喜欢使用间隔,你可以改变这样做的方式,这只是进行理论测试的最简单方法。

onShow: function(){
    // This will start loading of the content in web-view
    this.setData({webURL: this.data.webBaseURL } );

    // Sends message from message queue to web-view
    let _this = this;
    setInterval(function(e) {
        if( _this.data.messageQueueSize < 1 ) return;
        _this.data.messageQueueSize --;
        let msg = _this.data.messageQueue.splice(0,1);
        _this.setData({webURL: _this.data.webBaseURL+"#"+msg});
    },250);
}

您可以看到该消息作为散列附加到 web-view 源 (url)。

webBaseURL 用于生成带有哈希的最终 URL,然后发送到 web-view.

4。向队列添加消息

要在消息队列中创建消息,只需在您的页面中定义以下方法:

addMessageToQueue: function(obj) {
    obj.unique = Math.round(Math.random()*100000);
    let msg = b64.string2base64(JSON.stringify(obj));
    this.data.messageQueue.push(msg);
    this.data.messageQueueSize++;
}

无论何时调用此方法,只需传递一个具有您需要的任何属性的对象,它将转换为 JSON 字符串,然后转换为 base64 字符串,最后附加到消息队列中。

添加

unique 属性 以使生成的 base64 结果始终不同,即使其余对象属性相同 - 我只是为了我的项目目的而需要它。如果你不需要它,你可以忽略它/删除它。

由于存在时间间隔 运行 并检查消息队列,所有像这样添加的消息都将按照添加到队列中的相同顺序发送到 web-view。

现在只剩下一件事了——在我们加载到 web-view:

的 HTML 页面中添加哈希变化监听

HTMLWeb-app

1。监听哈希变化

window.addEventListener("hashchange",function(e){
    let messageBase64 = window.location.hash.substr(1);
    let json = window.atob( messageBase64 );
    let data = JSON.parse(json);
    console.log("Received data from mini-program:",data);
});

在小米8 Pro上测试。我还没有测试在中国销售的其他设备。

干杯!