uniapp的vue页面和非全屏webview交换数据的方式
在uniapp开发中,有时候我们需要在vue页面中嵌入一个webview组件,用来加载一些本地或远程的网页。但是,如何在vue页面和webview之间实现数据的传递和通信呢?常用的方法是使用uniapp官方提供的组件webview ,使用uni-app提供的UniAppJSBridgeReady事件和postMessage方法,来实现vue页面和webview之间的双向数据交换。但是这种方法有一定的局限性,webview组件设置的宽高等样式只有h5有效,在app中显示只能全屏加载,无法在app中实现vue页面和webview同屏交互,本文将介绍另一种自建webview的方法,可以在app中自定义webview的宽高及显隐。
首先,我们需要在vue页面中自建一个webview组件,代码如下,下面的代码自建了webview,并且完成了vue页面对html页面数据的接收和发送:
<template></template><script>export default { data() { return { topHeight: 0, windowHeight: 0, url: "/hybrid/html/test.html", fun: null, } }, methods: { //初始化 init() { // 获取系统信息,用于设置webview位置 var _this = this; uni.getSystemInfo({ success: function(res) { _this.topHeight = res.statusBarHeight _this.windowHeight = res.windowHeight } }) // #ifdef APP-PLUS //自建webview //如果当前的文件为直接在pages.json声明的vue文件使用this.$scope.$getAppWebview(), //如果当前的文件为pages.json声明的vue文件引用的子组件,使用this.$parent.$scope.$getAppWebview() var currentWebview = this.$parent.$scope.$getAppWebview(); var height = this.windowHeight - this.topHeight; wv = plus.webview.create(this.url, "webview", { // plusrequire: "none", //注释后会无法使用数据交换,请勿放开注释 // 'uni-app': 'none',//注释后会无法使用数据交换,请勿放开注释 top: this.topHeight + 20,//根据你想要的样式设置top scalable: true,//缩放 width: '100%',//根据你想要的样式设置宽度 height: height - 202//根据你想要的样式设置高度
}) currentWebview.append(wv); //监听子html页面uni.postMessage返回的值,html页面触发plusMessage事件时会自动调用fun函数,实现对html页面返回值的接收和利用 let that = this this.fun = function(msg) { if (msg.data.args.data.name == 'postMessage') { let msgData = msg.data.args.data.arg console.log('app接收到消息为:' + JSON.stringify(msgData));
} } plus.globalEvent.addEventListener('plusMessage', this.fun); // #endif }, //调用该函数关闭webview渲染 close() { // #ifdef APP-PLUS if (wv) { plus.webview.close(wv); wv = null } // #endif }, // 发送数据给html页面,本质上是执行了plus渲染的wv上携带的eval() 函数,下面的getData就是html页面要声明的getData函数,通过这种方法传递数据给html页面 evalJs(msg = "来自vue页面的参数") { // #ifdef APP-PLUS let str = `getData(${JSON.stringify(msg)})` if (wv) { wv.evalJS(str); } // #endif } }}</script><style></style>接下来,我们需要在html页面中监听UniAppJSBridgeReady事件,这个事件会在webview加载完成后触发。在这个事件的回调函数中,我们可以获取到webview的对象,然后调用它的postMessage方法,向网页发送数据。这里我们假设要发送的数据是一个字符串”Hello, webview!”。代码如下:
<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /> <title>map</title> <style type="text/css"> html, body { height: 100%; margin: 0; overflow: hidden; } </style> <!-- 重要,引入了才能交互数据,具体文件可以在uniapp官网下载 --> <script src="./js/uni.webview.1.5.4.js"></script>
</head> <body> <button id="postData">给app的页面发送数据</button> </body> <script> //组件通信 //发送数据到vue组件 //UniAppJSBridgeReady事件会在uni.webview.js相关代码加载完成后触发,触发后就可以使用postMessage方法发送数据,一般可以在这个事件里调用一次postMessage来判断代码是否正常运行. document.addEventListener('UniAppJSBridgeReady', function() { let message = { action: 'hello world' } uni.postMessage({ data: message }); }); //自定义按钮数据发送 let btn = document.getElementById("postData") btn.addEventListener("click", (e) => { uni.postMessage({ data: { action: "Hello, webview!", // 这是传的参数 }, }); }) //接收vue组件的数据 window.getData = function(msgList) { console.log('接收vue组件传递来的数据:' + JSON.stringify(msgList)); } </script></html>总结一下,使用webview组件时,我们可以利用evalJS方法和postMessage方法,来实现vue页面和webview之间的双向数据交换。这样,我们就可以在uniapp中灵活地使用webview组件,来加载一些本地或远程的网页,并与它们进行通信,如果需要的就是全屏加载webview,那就不必使用本文的方法了,webview组件使用更方便一些,但是如果你需要更复杂的交互,还是自建webview更合理一些。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!