我正在构建微信小程序,该程序的其中一个页面具有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),其中包括来自WeChat的jweixin-1.3.2.js
lib,用于与WeChat API连接以及与父小程序连接。页面为空,没有DOM元素,只有加载文档时将执行的javascript。
它具有像这样的javascript:
index.js
document.addEventListener('DOMContentLoaded',function(){
wx.miniProgram.postMessage({data:'test'});
});
我能够将文档中的消息发布到小型程序中,而不会出现问题。还可以发送一些小程序导航命令,例如wx.miniProgram.navigateTo({url:'path/to/page'});
,所以一切似乎都很好。 web-view
完成加载后,我还可以在小型程序中获得回调。
问题:
如何从小程序中将消息 发布到网络视图?例如,将字符串或对象传递到Web视图。
我已经搜寻了几个小时,似乎找不到任何人这样做,但是我不敢相信这只是一种单向的沟通。
任何帮助或想法都会受到赞赏!
答案 0 :(得分:0)
我已经找到了一种将数据从小程序传递到Web视图内容的有效方法,而且目前看来,这是唯一可行的方法。
您将需要能够将普通String转换为Base64字符串。小型程序API具有将字节数组转换为base64字符串的方法,但是不能用于此目的。因此,创建您自己的模块来完成该任务:
文件:lib/b64.js
var string2base64 = function(str) {
.... here put your js code for making b64 string ....
return result;
};
module.exports = {
string2base64
};
在具有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
对象中,添加webURL
和webBaseURL
属性,如下所示:
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视图的待处理消息。
messageQueueSize
只是数组长度。用于更好的性能,以避免读取Array.length。
在页面的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视图源(url)。
webBaseURL
用于生成带有哈希值的最终URL,然后将其发送到网络视图。
要在消息队列中创建消息,只需在页面中定义以下方法:
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++;
}
无论何时调用此方法,只需传递一个具有所需属性的Object,它将转换为JSON字符串,然后转换为base64字符串,最后附加到消息队列中。
添加了 unique
属性,以使生成的base64结果始终不同,即使其余对象属性都相同-我只是出于项目目的而已。您可以忽略它,或者在不需要它时将其删除。
由于在消息队列上运行并检查间隔,所有这样添加的消息将按照添加到队列的顺序发送到Web视图。
现在只剩下一件事了-在我们已加载到网络视图的HTML页面中添加哈希更改侦听:
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);
});
在Xiaomi Mi8 Pro上测试。我尚未在中国销售的其他设备上进行测试。
干杯!