双向实时
如果app端部署成网站,则web-view就是iframe,使用也可以双向通讯
https://uniapp.dcloud.net.cn/component/web-view.html
APP端代码
index.vue:
<template>
<web-view
id="m-webview"
:fullscreen="true"
:src="webViewSrc"
:webview-styles="{ height: '400px' }"
@message="handleMessage"
@onPostMessage="handlePostMessge"
@load="handleLoad"
@error="handleError"
></web-view>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
let webViewSrc = ref('')
let webview: any
//#region 事件
const handleH5Message = (value: any) => {
console.log('父应用接收消息,handleH5Message', value.data.data)
handleH5PostMessage()
}
const handleMessage = (value: any) => {
console.log('父应用接收消息,handleMessage', value)
webview.evalJS('globalCallbackForApp("点击")')
if (Array.isArray(value.detail?.data) && value.detail.data.length > 0) {
if (
value.detail.data[0].type === 'msg' &&
value.detail.data[0].value === 'chooseImage'
) {
if (value.detail.data[0].callback) {
webview.evalJS(`${value.detail.data[0].callback}("自定义点击")`)
}
uni.chooseImage({
count: 1, // 默认9, 设置图片的选择数量
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], // 从相册选择
success: (res) => {
// 返回选定照片的本地文件路径列表 tempFilePaths
console.log(res.tempFilePaths)
},
fail: (err) => {
// 处理错误
console.error(err)
},
})
}
}
}
const handlePostMessge = (value: any) => {
console.log('handlePostMessge', value)
}
const handleLoad = (value: any) => {
console.log('handleLoad', value)
}
const handleError = (value: any) => {
console.log('handleError', value)
}
//#endregion
const handleMessageInit = () => {
// #ifdef H5
window.removeEventListener('message', handleH5Message)
window.addEventListener('message', handleH5Message)
// #endif
}
const handleH5PostMessage = () => {
var iframe: any = document.getElementById('m-webview')
var message = {
target: 'iframe',
data: 'Hello, I am your parent',
}
console.log('父应用发送消息', message)
iframe.contentWindow.postMessage(message, '*')
}
const init = (option: any) => {
handleMessageInit()
webViewSrc.value = option.webViewUrl
// #ifdef APP-PLUS
//https://uniapp.dcloud.net.cn/tutorial/page.html#getappwebview
let pages = getCurrentPages()
let page: any = pages[pages.length - 1]
let currentWebview = page.$getAppWebview()
setTimeout(() => {
webview = currentWebview.children()[0]
console.log('this.wvNode.evalJS2', typeof webview.evalJS)
if (typeof webview.evalJS === 'function') {
console.log('执行')
webview.evalJS('globalCallbackForApp("初始化")')
}
}, 1000)
// #endif
}
onLoad((option) => {
init(option)
})
</script>
<style lang="scss" scoped></style>
被嵌入的网页端代码
list-user.vue:
<template>
<view>
<view class="m-title">工艺报警</view>
<text>{{ title }}</text>
<view class="m-btn-wrap">
<cl-button @click="handleClick">打开相册</cl-button>
</view>
</view>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
const title = ref("");
//#region 事件
const handleFormatPostMessageData = (value: any) => {
if (typeof value.callbackFun === "function") {
window[value.callback] = value.callbackFun;
delete value.callbackFun
}
return {
...value,
};
};
const handleClick = () => {
console.log("子应用发送消息");
webViewUni.postMessage({
data: handleFormatPostMessageData({
type: "msg",
value: "chooseImage",
callback: "customCallbackClick",
callbackFun: (data: any) => {
console.log("子应用接收父应用的实时消息【自定义】:", data);
},
}),
});
};
//#endregion
const init = () => {
window.addEventListener(
"message",
function (event) {
if (event.data.target === "iframe") {
console.log("子应用接收消息:", event.data.data);
}
},
false,
);
};
onLoad(() => {
init();
});
</script>
<style lang="scss" scoped>
.m-title {
padding: 20rpx;
color: #666;
font-size: 40rpx;
}
.m-btn-wrap {
padding: 20rpx;
}
</style>
hybrid_html_uni.webview.1.5.5.js:
!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 i(e,i){return n.call(e,i)}var t=[];function o(){return window.__dcloud_weex_postMessage||window.__dcloud_weex_}function a(){return window.__uniapp_x_postMessage||window.__uniapp_x_}var r=function(e,n){var i={options:{timestamp:+new Date},name:e,arg:n};if(a()){if("postMessage"===e){var r={data:n};return window.__uniapp_x_postMessage?window.__uniapp_x_postMessage(r):window.__uniapp_x_.postMessage(JSON.stringify(r))}var d={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__uniapp_x_postMessage?window.__uniapp_x_postMessageToService(d):window.__uniapp_x_.postMessageToService(JSON.stringify(d))}else if(o()){if("postMessage"===e){var s={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(s):window.__dcloud_weex_.postMessage(JSON.stringify(s))}var w={type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(w):window.__dcloud_weex_.postMessageToService(JSON.stringify(w))}else{if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:i,pageId:""},"*");if(0===t.length){var u=plus.webview.currentWebview();if(!u)throw new Error("plus.webview.currentWebview() is undefined");var g=u.parent(),v="";v=g?g.id:u.id,t.push(v)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:i,webviewIds:t}},"__uniapp__service");else{var c=JSON.stringify(i);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(c,",").concat(JSON.stringify(t),");"))}}},d={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;r("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;r("redirectTo",{url:encodeURI(n)})},getEnv:function(e){a()?e({uvue:!0}):o()?e({nvue:!0}):window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};r("postMessage",e.data||{})}},s=/uni-app/i.test(navigator.userAgent),w=/Html5Plus/i.test(navigator.userAgent),u=/complete|loaded|interactive/;var g=window.my&&navigator.userAgent.indexOf(["t","n","e","i","l","C","y","a","p","i","l","A"].reverse().join(""))>-1;var v=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 p=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var _=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var m=window.qa&&/quickapp/i.test(navigator.userAgent);var f=window.ks&&window.ks.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var l=window.tt&&window.tt.miniProgram&&/Lark|Feishu/i.test(navigator.userAgent);var E=window.jd&&window.jd.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var x=window.xhs&&window.xhs.miniProgram&&/xhsminiapp/i.test(navigator.userAgent);for(var S,h=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},y=[function(e){if(s||w)return window.__uniapp_x_postMessage||window.__uniapp_x_||window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&u.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),d},function(e){if(_)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(g){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(v)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(p)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(m){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){if(f)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.ks.miniProgram},function(e){if(l)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(E)return window.JDJSBridgeReady&&window.JDJSBridgeReady.invoke?setTimeout(e,0):document.addEventListener("JDJSBridgeReady",e),window.jd.miniProgram},function(e){if(x)return window.xhs.miniProgram},function(e){return document.addEventListener("DOMContentLoaded",e),d}],M=0;M<y.length&&!(S=y[M](h));M++);S||(S={});var P="undefined"!=typeof uni?uni:{};if(!P.navigateTo)for(var b in S)i(S,b)&&(P[b]=S[b]);return P.webView=S,P}));
index.html
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<script>
window.globalCallbackForApp = function (value) {
console.log("子应用接收父应用的实时消息【全局】", value);
};
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" : "") +
'" />',
);
</script>
<script src="/src/static//js/hybrid_html_uni.webview.1.5.5.js"></script>
<!-- <script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=PB3X34j5vGW07DLETDN11qtTrrV1fn8M"></script> -->
<script type="text/javascript">
window.webViewUni = uni;
// 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。
document.addEventListener("UniAppJSBridgeReady", function () {
// webViewUni.postMessage({
// data: {
// action: "message",
// },
// });
// webViewUni.getEnv(function (res) {
// console.log("当前环境:" + JSON.stringify(res));
// });
});
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
APP端代码(选项式)
<template>
<web-view
ref="webview"
src="http://11.2.244.245:9901/pages/home/list-user/index"
:fullscreen="false"
id="m-webview"
></web-view>
</template>
<script lang="ts">
export default {
data() {
return {
webUrl: '',
wvNode: null,
}
},
onReady() {
// #ifdef APP-PLUS
var currentWebview = this.$scope.$getAppWebview() //此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
setTimeout(() => {
this.wvNode = currentWebview.children()[0]
console.log('currentWebview', currentWebview)
console.log('this.wvNode.evalJS1', this.wvNode)
console.log('this.wvNode.evalJS', typeof this.wvNode.evalJS)
console.log('执行')
this.wvNode.evalJS('msgFromApp("来着父组件的消息")')
}, 1000)
// #endif
},
onHide() {
// console.log('patrol-h5-onHide')
// #ifdef APP-PLUS
const name = 'stop'
this.wvNode.evalJS("msgFromApp('" + name + "')")
// console.log('---currentWebview---wvNode---onHide=',this.wvNode.evalJS)
// #endif
},
}
</script>
<style lang="scss" scoped></style>
https://uniapp.dcloud.net.cn/tutorial/page.html#getappwebview
参考链接
https://juejin.cn/post/7230727650259025980
人工智能学习网站
https://chat.xutongbao.top