uniapp 打包 H5 实现在 uniapp 打包 APP 的 webview 通信

Brod_Roy 2024-07-26 11:03:04 阅读 99

一、前言

遇到 uniapp 打包的 APP 在 webview 内嵌入 uniapp 打包的 H5 页面的需求,并实现通信。本篇主要总结了如何实现并总结遇到的问题,希望可以帮助大家减少负担。

实现需求主要有三个地方需要处理:

index.html 的打包配置导入 uni.webview.js使用 myUni.getEnv() 导入和 myUni.webView.postMessage() 导出

二、index.html 的打包配置

直接拷贝覆盖 index.html 即可

<code><!DOCTYPE html>

<html lang="zh-CN">code>

<head>

<meta charset="utf-8">code>

<meta http-equiv="X-UA-Compatible" content="IE=edge">code>

<title>

<%= htmlWebpackPlugin.options.title %>

</title>

<!-- Open Graph data -->

<!-- <meta property="og:title" content="Title Here" /> -->code>

<!-- <meta property="og:url" content="http://www.example.com/" /> -->code>

<!-- <meta property="og:image" content="http://example.com/image.jpg" /> -->code>

<!-- <meta property="og:description" content="Description Here" /> -->code>

<script>

var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || CSS

.supports('top: constant(a)'))

document.write(

'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +

(coverSupport ? ', viewport-fit=cover' : '') + '" />')code>

</script>

<link rel="stylesheet" href="<%= BASE_URL %>static/index.<%= VUE_APP_INDEX_CSS_HASH %>.css" />code>

</head>

<body>

<noscript>

<strong>Please enable JavaScript to continue.</strong>

</noscript>

<div id="app"></div>code>

<!-- built files will be auto injected -->

<script type="text/javascript">code>

var userAgent = navigator.userAgent;

if (userAgent.indexOf('AlipayClient') > -1) {

// 支付宝小程序的 JS-SDK 防止 404 需要动态加载,如果不需要兼容支付宝小程序,则无需引用此 JS 文件。

document.writeln('<script src="https://appx/web-view.min.js"' + '>' + '<' + '/' + 'script>');code>

} else if (/QQ/i.test(userAgent) && /miniProgram/i.test(userAgent)) {

// QQ 小程序

document.write(

'<script type="text/javascript" src="https://qqq.gtimg.cn/miniprogram/webview_jssdk/qqjssdk-1.0.0.js"><\/script>'code>

);

} else if (/miniProgram/i.test(userAgent) && /micromessenger/i.test(userAgent)) {

// 微信小程序 JS-SDK 如果不需要兼容微信小程序,则无需引用此 JS 文件。

document.write('<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"><\/script>');code>

} else if (/toutiaomicroapp/i.test(userAgent)) {

// 头条小程序 JS-SDK 如果不需要兼容头条小程序,则无需引用此 JS 文件。

document.write(

'<script type="text/javascript" src="https://s3.pstatp.com/toutiao/tmajssdk/jssdk-1.0.1.js"><\/script>');code>

} else if (/swan/i.test(userAgent)) {

// 百度小程序 JS-SDK 如果不需要兼容百度小程序,则无需引用此 JS 文件。

document.write(

'<script type="text/javascript" src="https://b.bdstatic.com/searchbox/icms/searchbox/js/swan-2.0.18.js"><\/script>'code>

);

} else if (/quickapp/i.test(userAgent)) {

// quickapp

document.write('<script type="text/javascript" src="https://quickapp/jssdk.webview.min.js"><\/script>');code>

}

</script>

<!-- uni 的 SDK -->

<script type="text/javascript" src="<%= BASE_URL %>static/uni.webview.js"></script>code>

<script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.3/index.js"></script>code>

<script type="text/javascript">code>

// 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。

document.addEventListener('UniAppJSBridgeReady', function() {

uni.postMessage({

data: {

action: 'message'

}

});

uni.getEnv(function(res) {

console.log('当前环境:' + JSON.stringify(res));

});

});

document.addEventListener('UniAppJSBridgeReady', function() {

console.log('UniAppJSBridgeReady');

webUni.getEnv(function(res) {

console.log('当前环境:' + JSON.stringify(res));

});

});

</script>

</body>

</html>

三、导入 uni.webview.js

image-20240621095500277

在文件根目录下新建 utils 目录,新建 uni.webview.1.5.2.js ,拷贝代码导入:

<code>!function(e,n){ "object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){ "use strict";try{ var e={ };Object.defineProperty(e,"passive",{ get:function(){ !0}}),window.addEventListener("test-passive",null,e)}catch(e){ }var n=Object.prototype.hasOwnProperty;function t(e,t){ return n.call(e,t)}var i=[],a=function(e,n){ var t={ options:{ timestamp:+new Date},name:e,arg:n};if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){ if("postMessage"===e){ var a={ data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(a):window.__dcloud_weex_.postMessage(JSON.stringify(a))}var o={ type:"WEB_INVOKE_APPSERVICE",args:{ data:t,webviewIds:i}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(o):window.__dcloud_weex_.postMessageToService(JSON.stringify(o))}if(!window.plus)return window.parent.postMessage({ type:"WEB_INVOKE_APPSERVICE",data:t,pageId:""},"*");if(0===i.length){ var r=plus.webview.currentWebview();if(!r)throw new Error("plus.webview.currentWebview() is undefined");var d=r.parent(),s="";s=d?d.id:r.id,i.push(s)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({ type:"WEB_INVOKE_APPSERVICE",args:{ data:t,webviewIds:i}},"__uniapp__service");else{ var w=JSON.stringify(t);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(w,",").concat(JSON.stringify(i),");"))}},o={ navigateTo:function(){ var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{ },n=e.url;a("navigateTo",{ url:encodeURI(n)})},navigateBack:function(){ var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{ },n=e.delta;a("navigateBack",{ delta:parseInt(n)||1})},switchTab:function(){ var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{ },n=e.url;a("switchTab",{ url:encodeURI(n)})},reLaunch:function(){ var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{ },n=e.url;a("reLaunch",{ url:encodeURI(n)})},redirectTo:function(){ var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{ },n=e.url;a("redirectTo",{ url:encodeURI(n)})},getEnv:function(e){ window.plus?e({ plus:!0}):e({ h5:!0})},postMessage:function(){ var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{ };a("postMessage",e.data||{ })}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){ window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{ bubbles:!0,cancelable:!0}))},f=[function(e){ if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){ if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){ if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){ if(w){ document.addEventListener("DOMContentLoaded",e);var n=window.my;return{ navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){ if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){ if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){ if(p){ window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{ navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){ return document.addEventListener("DOMContentLoaded",e),o}],m=0;m<f.length&&!(l=f[m](_));m++);l||(l={ });var E="undefined"!=typeof uni?uni:{ };if(!E.navigateTo)for(var b in l)t(l,b)&&(E[b]=l[b]);return E.webView=l,E}));code>

打开 main.js 导入 uni.webview.1.5.2.js:

import App from './App'

// #ifndef VUE3

import Vue from 'vue'

import './uni.promisify.adaptor'

// ***************************** 导入 ***************************** //

import * as uni from './utils/uni.webview.1.5.2.js'

document.addEventListener("UniAppJSBridgeReady", function() { // 这里必须更换uni,不然指向有误

Vue.prototype.myUni = uni

});

// *************************************************************** //

Vue.config.productionTip = false

App.mpType = 'app'

const app = new Vue({

...App

})

app.$mount()

// #endif

// #ifdef VUE3

import { createSSRApp } from 'vue'

export function createApp() {

const app = createSSRApp(App)

return {

app

}

}

// #endif

四、页面使用

webview 页面:

<template>

<view>

<web-view @message="message" :src="url"></web-view>code>

</view>

</template>

<script>

export default {

data() {

return {

url: 'http://XXX.XXX.X.XXX:XXXX/?data='

};

},

onLoad() {

let data = [{

name:'测试数据'code>

}]

this.url += encodeURIComponent(JSON.stringify(data))

},

methods: {

// 在小程序中没办法这样轻松获取数据,只有在离开页面、转发、销毁等情况下才可以获取,十分离谱

message(arg) { // 获取 H5 提交参数

console.log(arg)

},

}

};

</script>

H5 页面

<template>

<view @click="sendMessage()"></view>code>

</template>

<script>

export default {

data() {

return {

}

},

mounted() {

let data = this.getQuery('data') // 获取页面信息

console.log('data=============>>>>>>>>', JSON.parse(data));

},

methods: {

//取url中的参数值

getQuery(name) {

// 正则:[找寻'&' + 'url参数名字' = '值' + '&']('&'可以不存在)

let reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");

let r = window.location.search.substr(1).match(reg);

console.log(r);

if (r != null) {

// 对参数值进行解码

return decodeURIComponent(r[2]);

}

return null;

},

sendMessage() { // 提交参数

let that = this;

this.myUni.webView.postMessage({ // 提交参数一定要放在data内

data: {

id: 0,

text: 'Id'

},

});

},

}

}

</script>

五、参考

webview使用uniapp项目开发无法使用uni.postMessage(踩坑经验分享) - DCloud问答

uniapp使用webview嵌入vue页面及通信_uniapp webview页面和嵌入的子页面通信-CSDN博客

如何在uniapp中优雅地使用WebView - 林恒 - 博客园 (cnblogs.com)

web-view | uni-app官网 (dcloud.net.cn)

如何在uniapp中优雅地使用WebView - 林恒 - 博客园 (cnblogs.com)

web-view | uni-app官网 (dcloud.net.cn)

uni-app和web-view页面相互传参_uniapp webview传参-CSDN博客



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。