问题背景:
当 【H5】 嵌入到 【APP端】 后,想进行通讯,比如H5调用 APP端的扫描功能。该如何实现?
之前想过用 webView 但是 webView 会铺满窗口 这个有点不满足需求。
所以采用 iframe+ renderjs 的方式解决。
附上 renderjs 官方说明
https://uniapp.dcloud.net.cn/tutorial/renderjs.html#renderjs
下面以 H5端 点击按钮 调用APP端的扫描,然后将扫描结果返回H5端为案例
【APP端】代码
<template>
<view>
<iframe style="width:100%;height:100%" id="iframe1" ref="iframe1" :src="url" width="100%" frameborder="0"></iframe>
<!-- 主要是为了触发 renderjs -->
<view
id="renderjs-view"
style="display: none;"
:msg="msg"
:change:msg="renderModal.receiveMsg"
/>
</view>
</template>
<script>
export default{
data(){
return{
msg:"",//当这个值发生改变时 就会触发renderModal.receiveMsg 方法
url:"http://xxxxx", //改成你自己要嵌入的地址
}
},
methods:{
//向 H5 发送消息
sendMessage(data){
data._Key=getGuid();//主要是为了触发 renderModal.receiveMsg 方法
this.msg=JSON.stringify(data);
},
//================ APP API方法,由H5端调用============
openScan(){
// 调起条码扫描
console.log("[APP端]调用扫描");
uni.scanCode({
success: (res)=> {
this.sendMessage({
msg:res.result
});
}
});
}
}
}
</script>
<script module="renderModal" lang="renderjs">
export default {
data() {
return {
dom: '',
}
},
mounted() {
this.dom = document.getElementById('iframe1')
console.log("[APP端]开启监听");
window.addEventListener('message', this.postMessage);
},
methods: {
receiveMsg(data){
const newData= JSON.parse(data);
delete newData._Key;//将这个参数删掉,不发送到H5端
this.sendMessage(newData);
},
//APP端接收到的消息
postMessage(e){
console.log("[APP端]接收到的消息==>",e.data);
//var params=JSON.parse(e.data);
//调用打开扫描的方法
this.$ownerInstance.callMethod("openScan");
},
//发送消息
sendMessage(data){
console.log("[APP端]发送消息",JSON.stringify(data));
// * 号可以改成你自己的 域名,不改也行
this.dom.contentWindow.postMessage(JSON.stringify(data),'*')
},
}
}
</script>
补一个 getGuid() 方法,主要保证每次调用 sendMessage 都能触发 receiveMsg
/**
* 获取32位guid
* @param {*} fg 分隔符,默认不分割
* @returns
*/
export function getGuid(fg = "") {
let guid = getId(fg);
//后面的数据位,完全采用随机数产生
for (var i = 12; i <= 32; i++) {
var g = Math.floor(Math.random() * 16).toString(16);
guid += g;
if (i == 12 || i == 16 || i == 20) {
guid += fg;
}
}
return guid.toUpperCase();
}
function getId(fg) {
var guid = "";
var prefix11 = ""; //基于时间产生的随机数
var d = new Date();
var x = Math.random(); //获取一个0~1之间的随机数
var y = d.getTime(); //返回 1970 年 1 月 1 日至今的毫秒数
if (x < 0.1) x += 0.1;
//根据当前日期,产生GUID的前11位,避免GUID重复,引入一个随机数
prefix11 = Math.round(x * y * 10).toString(16);
guid += prefix11.substring(0, 8);
guid += fg;
guid += prefix11.substring(8, 11);
return guid;
}
【H5端】代码
<template>
<view>
扫描结果:
<input v-model="msg"/>
<button @click="openScan">打开扫描</button>
</view>
</template>
<script>
export default{
data(){
return{
msg:""
}
},
onLoad(){
//H5端 开启监听
window.addEventListener("message", this.postMessage);
},
methods:{
//H5端 接收消息
postMessage(e){
console.log("[H5端]H5接收的数据===>", e.data);
const data= JSON.parse(e.data);
this.msg=data.result;
},
//H5端 向APP发送消息
sendMessage(data){
//这个方法可以自行改造,可通过参数来决定调用 APP端的哪个方法
window.parent.postMessage("你的参数,只能是字符串类型", "*");
},
openScan(){
this.sendMessage({});
}
}
}
</script>