uniapp(H5 和 App) 与 Web 端,完整代码,真正解决通信问题
微光无限 2024-08-31 14:03:01 阅读 86
先去官网了解下webview web-view | uni-app官网 (dcloud.net.cn)
uniapp
1.要嵌入 webview 的 index.vue 文件
<code><template>
<view>
<web-view :src="reportSrc" :webview-styles="webviewStyles" :update-title="false" @message="message"></web-view>code>
<!-- 如果要在当前已经嵌入webview文件的页面加按钮的话,需要调整webview的高度,因为默认是撑满整个页面 -->
<button style="position: fixed;bottom: 0;width: 100%;" type="primary" @click="submit">发送打印请求</button>code>
</view>
</template>
<script>
//计划创建的webview(必须写,否则会报错)
var wv;
export default {
data() {
return {
// 调整webview页面的高度为85%,这样固定在页面底部的按钮就可以显示出来了
webviewStyles: {
width: '100%',
height: '85%'
},
// 要嵌入的web页面地址
reportSrc: '',
};
},
created() {
// web端的网页地址(如果是本地跑的 html 的话需要使用 vscode中的 live server 打开该 html 文件
// 然后你发现那个 html文件的地址是 http://127.0.0.1:5500/index.html , 这个地址需要替换成当前电脑的 ip地址 如 192.166.66.117
// 最后 webview 引用的网页地址是 http://192.166.66.117:5500/,很多的答案都直接忽略了这里,导致我尝试了很多次在手机上都不成功!
this.reportSrc = `http://192.166.66.117:5500/`
},
onLoad() {
// App端
// #ifdef APP-PLUS
//此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
uni.showLoading({
title: '加载中'
});
var currentWebview = this.$scope.$getAppWebview()
setTimeout(function() {
wv = currentWebview.children()[0]
uni.hideLoading()
}, 1000); //如果是页面初始化调用时,需要延时一下
// #endif
// H5端
// #ifdef H5
window.addEventListener('message', e => {
this.webV = e.source // window的对象
// 接收Html发送过来的消息, 控制台打印看结果
console.log(e.data.data.arg, '接收h5页面发来的消息');
}, false)
// #endif
},
methods: {
// 手机上运行时点击 postMessage 会走这里
message(e) {
console.log('app上测试接收 webview 传过来的值', e.detail.data)
},
//uniapp 向 web 端传值
submit() {
let obj = {
name: 'wft'
}
// 这里解释下 evalJS 是什么东西
// evalJS是一种 JavaScript 注入技术,其原理是在运行时将动态生成的 JavaScript 代码注入到网页中,并且立即执行该代码。
// JavaScript 注入通常用于扩展或修改网页上的功能。它可以通过将自定义的 JavaScript 代码插入到网页的上下文中,来实现对网页的修改或操控。
// 注入的 JavaScript 代码可以访问和修改网页的 DOM 元素、调用网页提供的 API,以及与页面上的其他 JavaScript 代码进行交互。
//传递的参数如果是引用类型,就要 JSON.stringify 转一下,否则报错
// `msgFromUniapp(${JSON.stringify(obj)})` 这里其实相当于在 web 端调用了此方法
wv.evalJS(`msgFromUniapp(${JSON.stringify(obj)})`);
}
}
}
</script>
<style lang="scss" scoped>code>
</style>
web端
1.创建一个本地文件夹,并创建html等相关文件,具体如下
2.创建 uniwebview.js 文件,这个文件其实是 uniapp 的官方包,在我使用这个线上包的时候发生了报错,这里建议大家创建个本地文件,并在这个 html 引用这个文件
注意:下面的代码是当前 uniapp 中的webview.js 官方包体,版本是 1.1.5
<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 i(e, i) {
return n.call(e, i);
}
var t = [];
function r() {
return window.__dcloud_weex_postMessage || window.__dcloud_weex_;
}
var o = function (e, n) {
var i = {
options: {
timestamp: +new Date(),
},
name: e,
arg: n,
};
if (r()) {
if ('postMessage' === e) {
var o = {
data: [n],
};
return window.__dcloud_weex_postMessage
? window.__dcloud_weex_postMessage(o)
: window.__dcloud_weex_.postMessage(JSON.stringify(o));
}
var a = {
type: 'WEB_INVOKE_APPSERVICE',
args: {
data: i,
webviewIds: t,
},
};
window.__dcloud_weex_postMessage
? window.__dcloud_weex_postMessageToService(a)
: window.__dcloud_weex_.postMessageToService(JSON.stringify(a));
}
if (!window.plus)
return window.parent.postMessage(
{
type: 'WEB_INVOKE_APPSERVICE',
data: i,
pageId: '',
},
'*'
);
if (0 === t.length) {
var d = plus.webview.currentWebview();
if (!d) throw new Error('plus.webview.currentWebview() is undefined');
var s = d.parent(),
w = '';
(w = s ? s.id : d.id), t.push(w);
}
if (plus.webview.getWebviewById('__uniapp__service'))
plus.webview.postMessageToUniNView(
{
type: 'WEB_INVOKE_APPSERVICE',
args: {
data: i,
webviewIds: t,
},
},
'__uniapp__service'
);
else {
var u = JSON.stringify(i);
plus.webview
.getLaunchWebview()
.evalJS(
'UniPlusBridge.subscribeHandler("'
.concat('WEB_INVOKE_APPSERVICE', '",')
.concat(u, ',')
.concat(JSON.stringify(t), ');')
);
}
},
a = {
navigateTo: function () {
var e =
arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
n = e.url;
o('navigateTo', {
url: encodeURI(n),
});
},
navigateBack: function () {
var e =
arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
n = e.delta;
o('navigateBack', {
delta: parseInt(n) || 1,
});
},
switchTab: function () {
var e =
arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
n = e.url;
o('switchTab', {
url: encodeURI(n),
});
},
reLaunch: function () {
var e =
arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
n = e.url;
o('reLaunch', {
url: encodeURI(n),
});
},
redirectTo: function () {
var e =
arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
n = e.url;
o('redirectTo', {
url: encodeURI(n),
});
},
getEnv: function (e) {
r()
? e({
nvue: !0,
})
: window.plus
? e({
plus: !0,
})
: e({
h5: !0,
});
},
postMessage: function () {
var e =
arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
o('postMessage', e.data || {});
},
},
d = /uni-app/i.test(navigator.userAgent),
s = /Html5Plus/i.test(navigator.userAgent),
w = /complete|loaded|interactive/;
var u =
window.my &&
navigator.userAgent.indexOf(
['t', 'n', 'e', 'i', 'l', 'C', 'y', 'a', 'p', 'i', 'l', 'A']
.reverse()
.join('')
) > -1;
var g =
window.swan && window.swan.webView && /swan/i.test(navigator.userAgent);
var v =
window.qq &&
window.qq.miniProgram &&
/QQ/i.test(navigator.userAgent) &&
/miniProgram/i.test(navigator.userAgent);
var c =
window.tt &&
window.tt.miniProgram &&
/toutiaomicroapp/i.test(navigator.userAgent);
var m =
window.wx &&
window.wx.miniProgram &&
/micromessenger/i.test(navigator.userAgent) &&
/miniProgram/i.test(navigator.userAgent);
var p = 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 _ =
window.jd &&
window.jd.miniProgram &&
/micromessenger/i.test(navigator.userAgent) &&
/miniProgram/i.test(navigator.userAgent);
var E =
window.xhs &&
window.xhs.miniProgram &&
/xhsminiapp/i.test(navigator.userAgent);
for (
var h,
P = function () {
(window.UniAppJSBridge = !0),
document.dispatchEvent(
new CustomEvent('UniAppJSBridgeReady', {
bubbles: !0,
cancelable: !0,
})
);
},
b = [
function (e) {
if (d || s)
return (
window.__dcloud_weex_postMessage || window.__dcloud_weex_
? document.addEventListener('DOMContentLoaded', e)
: window.plus && w.test(document.readyState)
? setTimeout(e, 0)
: document.addEventListener('plusready', e),
a
);
},
function (e) {
if (m)
return (
window.WeixinJSBridge && window.WeixinJSBridge.invoke
? setTimeout(e, 0)
: document.addEventListener('WeixinJSBridgeReady', e),
window.wx.miniProgram
);
},
function (e) {
if (v)
return (
window.QQJSBridge && window.QQJSBridge.invoke
? setTimeout(e, 0)
: document.addEventListener('QQJSBridgeReady', e),
window.qq.miniProgram
);
},
function (e) {
if (u) {
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 (g)
return (
document.addEventListener('DOMContentLoaded', e),
window.swan.webView
);
},
function (e) {
if (c)
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) {
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 (_)
return (
window.JDJSBridgeReady && window.JDJSBridgeReady.invoke
? setTimeout(e, 0)
: document.addEventListener('JDJSBridgeReady', e),
window.jd.miniProgram
);
},
function (e) {
if (E) return window.xhs.miniProgram;
},
function (e) {
return document.addEventListener('DOMContentLoaded', e), a;
},
],
y = 0;
y < b.length && !(h = b[y](P));
y++
);
h || (h = {});
var B = 'undefined' != typeof uni ? uni : {};
if (!B.navigateTo) for (var S in h) i(h, S) && (B[S] = h[S]);
return (B.webView = h), B;
});
3.html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />code>
<meta
name="viewport"code>
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"code>
/>
<title>网络网页</title>
<style type="text/css">code>
.desc {
color: #999999;
}
* {
margin: 0;
padding: 0;
}
.btn {
display: block;
margin: 20px auto;
padding: 5px;
background-color: #007aff;
border: 0;
color: #ffffff;
height: 40px;
width: 200px;
}
.btn-red {
background-color: #dd524d;
}
</style>
</head>
<body>
<div id="app">code>
<p class="desc">code>
网页向应用发送消息,注意:小程序端应用会在此页面后退时接收到消息。
</p>
<div class="btn-list">code>
<button class="btn btn-red" type="button" id="postMessage">code>
postMessage
</button>
<input type="file" accept="image/*" multiple onchange="uploadImg()" />code>
</div>
</div>
<!-- 引用的是从uniapp官网上下载的 webview.js ,当前是 1.1.5 版本 -->
<script type="text/javascript" src="./uniwebview.js"></script>code>
<script type="text/javascript">code>
// 上传文件转 base64
var files = null;
function uploadImg(event) {
var e = window.event || event;
let Files = e.target.files[0];
var reader = new FileReader();
reader.readAsDataURL(Files); // 解析成base64格式
reader.onload = function () {
files = this.result;
};
}
// 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。
document.addEventListener('UniAppJSBridgeReady', () => {
document
.getElementById('postMessage')
.addEventListener('click', function () {
// 向uniapp传值
console.log(files);
uni.postMessage({
data: {
name: '流云借风真君',
age: '5000',
//这里尝试 web 端向 uniapp 传 blob 和 base64
//发现 app 端接收不到 blob,但是可以接收 base64
// H5 端可以接收 blob,也可以接收 base64
img: files,
},
});
});
});
// uniapp传过来的值
window.msgFromUniapp = function (arg) {
//传过来的值如果是复杂数据类型,需要 JSON.stringify 才能拿到
console.log('uniapp传过来的值', JSON.stringify(arg));
};
</script>
</body>
</html>
4.用 live server 运行这个 html 文件,再去 app 中和 H5 中测试通信
5.运行之后浏览器中应该是这样,此时这个地址是 live server 创建的一个服务,在H5 端能在 webview 中可以访问这个地址,但是app不行,因为 live server 创建的服务,app上并不能访问,但是只要你运行 app 用的是当前ip地址的电脑就可以用 app 访问这个 ip 地址,所以 uniapp 中的 webview 要引用当前运行项目的电脑的 ip 地址.
6.正确的地址应该是这样,记得加端口号
上一篇: Discord机器人与Webhooks:构建实时交互
本文标签
声明
本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。