摘要
本文记录了菜鸟作者在使用uniapp开发项目的过程中,遇到的众多问题中的一个:在开发支付宝小程序的webview与h5页面通信功能时遇到的坑,postMessage通信时h5页面跳转到webview首次打开的h5页面现象。
吐槽:兼容,多好听的词儿。
前言
开发工具: uniapp 3.1.18;支付宝小程序开发者工具 2.0 Stable
正文
内容不多,本文只做简述。
使用uniapp开发支付宝小程序时,使用webview打开h5页面后,可以通过@message事件和webViewContext.postMessage实现双向通信。以下展示代码:
小程序端的代码如下:
<web-view :src="src" @message="getMessage" ></web-view>
let webViewContext;
export default {
data() {
return {
src: '',
};
},
methods: {
/**
* 接收信息
*/
getMessage(e){
console.log("getMessage: ", e);
let method = e.detail.method;
let param = e.detail.param;
if (!webViewContext) {
webViewContext = my.createWebViewContext(e.target.id);
}
if (method == 'login') {
// todo something
}
if (method == "fedLogout") {
// todo something
}
if (method == "close") {
// todo something
}
},
/**
* 发送信息
*/
postMessage({method, data, code=200, msg}){
webViewContext.postMessage({
method: method,
data: data,
code: code,
msg: msg
});
},
}
};
细心的朋友可能发现了,webViewContext前面没有“this.”,这里没有写错,是故意的。为什么这么写,等稍后解释。
接下来是h5端的代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>
<%= htmlWebpackPlugin.options.title %>
</title>
<script>
// 引入支付宝jssdk
if (navigator.userAgent.indexOf('AlipayClient') > -1) {
document.writeln('<script src="https://appx/web-view.min.js"' + '>' + '<' + '/' + 'script>');
}
</script>
<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />
</head>
<body>
<noscript>
<strong>Please enable JavaScript to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
function login () {
return new Promise((resolve, reject) => {
/**
* 和小程序通信
*/
my.postMessage({
method: "login"
});
/**
* 监听小程序
*/
my.onMessage = function(response) {
console.log(response);
if (response.method == "login") {
if (response.code == 200) {
resolve(response.data);
} else {
reject(response.msg);
}
}
};
});
}
接下来说明一下,为什么不把webViewContext放在data里面,而是单独声明。
不卖关子,原因就是如果把webViewContext放在data中,当webViewContext变化时,会触发vue页面重新渲染,即使这个webViewContext没有放在页面元素里。当然,不只是webViewContext,只要是有可能变化的字段,都不能往data里放。这个小坑可是浪费了我不少时间!!!
作者水平有限,没有找到比较优雅的解决方法,为了解决这个问题,直接把webViewContext等字段放在了外面。如果有大佬知道怎么处理,还请不吝赐教。
后记
说一点题外话。
人生不如意,十之八九。就算你在某一方面有多努力,别人总会在其他方面指责你的不足。你尽力帮别人解决问题,未必就能够得到好的回报。
人还是得自己逗自己开心。不像我,只会心疼作者。