uniapp使用webview嵌入vue页面及通信实现方式
作者:会说法语的猪
前言
最近刚做的一个需求,web端(Vue)使用了FormMaking库,FormMaking是一个拖拉拽的动态设计表单、快速开发的一个东西,拖拽完之后最终可以导出一个很长的json,然后通过json再进行回显,快速开发,但是因为FormMaking是基于Vue和ElementUI的,uniapp中不能直接使用,只能采用webview的方式进行嵌入。就是把Vue项目中的要嵌入的页面加入到白名单,也就是不需要登陆就可以访问该页面,直接将该页面通过webview嵌入到uniapp中即可
本来想着是将uniapp中的token传到webview页面中,在要嵌入的webview页面(Vue页面)中去获取json进行渲染的,但是通过webview嵌入到uniapp中,在webview页面去发请求会有问题,本来uniapp做的就少一些,更是第一次做webview,所以这两天还是碰到不少坑。
最终方案就是在uniapp中获取那一大串儿json,然后传递到webview页面进行渲染,然后提交表单的时候再通知webview页面(Vue页面)将表单json再传递给uniapp进行提交。所以就涉及到了uniapp与webview之间的通信问题,接下来介绍:
1、uniapp中嵌入外部网页:
<template> <view class="index"> <web-view :update-title="false" :src="wvSrc" ></web-view> </view> </template> <script> export default { data() { return { wvSrc: "" } }, onLoad() { // #ifdef APP-PLUS this.wvSrc = `http://192.168.124.19:3000/#/index`; // #endif }, } </script> <style scoped> .index { width: 100%; height: 100%; position: relative; } </style>
就是直接给src复制就可以。上面给webview标签设置了update-title为false,它默认的是true,也就是默认webview嵌入进来上面的标题会跟随webview的自动更新,就会覆盖掉uniapp自身的标题,设置为false就不会覆盖
2、uniapp向webview页面传值
2.1. 先看第一种:通过路径传递
就是在嵌入的时候就直接在后面拼接上参数,但是这个最好只传递字符串,因为传递json对象的话在解析的时候可能会出问题,并不太推荐这种方式,如果只是一两个简短的字符串的话,还是可以的啦。
uniapp页面传递:
let tk = 'test_token' let id = 'pppppppiiiiiigggg' let status = 'start' this.wvSrc = `http://192.168.124.19:3000/#/index?params=${tk}WFT${id}WFT${status}`
webview页面接受:
首先得先引入一下:
public/index.html
<script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.3/index.js"></script>
或者进入浏览器输入该地址,Ctrl + A, Ctrl + C, 复制粘贴到本地,然后引入本地也是可以的,但是引入的时候一定是 import uni from '你的路径'
这样我们全局打印一下uni就会看到里面的方法:
然后在monted里面监听UniAppJSBridgeReady方法,也就是Vue该页面被嵌入到uniapp中的时候会触发,也就是可以使用uni的API了
mounted(){ console.log(uni) // 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。 document.addEventListener('UniAppJSBridgeReady', () => { console.log('UniAppJSBridgeReady-->') const [tk, id, status] = this.getQuery('params', 'hash').split('WFT') console.log(tk, 'tk-->>') console.log(id, 'id-->>') console.log(status, 'status-->>') }) }, methods: { // 解析url传递的参数 getQuery(name, type = 'search') { // const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)") // // const value = window.location.hash.substr(3).match(reg) // const value = window.location.search.substr(1).match(reg) // if (value) return decodeURIComponent(value[2]) // return null // type取值 search | hash return window.location[type].split(`${name}=`)[1] } }
如果你的Vue项目是hash模式路由参数就在window.lacation.hash中,如果不是就是window.location.search中,反正打印一下window.location就可以看到里面的信息了,再截取一下就OK了!
2.2. 第二种:通过调用当前的webview实例的evalJS方法
通过evalJS为这个子webview注入一段js。执行内部的逻辑
还有一点,webview优先级很高,并且默认都是全部覆盖app的,而且直接对其修改样式也是不起作用的,通过当前的webview实例对象也可以对其修改样式
一般我在嵌入的时候,就会拿到当前的webview实例,供后面使用
uniapp代码
// template代码 <button @tap="submit" class="btn">启动</button> //script代码 onLoad() { // #ifdef APP-PLUS this.wvSrc = `http://192.168.124.19:3000/#/index` setTimeout(() => { this.curWebview = this.$scope.$getAppWebview().children()[0] this.curWebview.setStyle({ height: '75%', scalable:true }) // scalable是否开启双指缩放 }, 500) //如果是页面初始化调用时,需要延时一下 // #endif }, methods: { //调用webview中的方法(注意getWebviewData一定是window上的方法,所以我们要在Vue页面中将对应的方法挂载到window上) submit() { let obj = { name: 'wft' } //传递的参数如果是引用类型,就要JSON.stringify转一下,否则报错 this.curWebview.evalJS(`getWebviewData(${JSON.stringify(obj)})`) } }
webview代码
<script> export default { created() { window.getWebviewData = this.getData }, methods: { //我们传递过来的是通过JSON.stringify转过的,但是到这儿之后直接转过来了,不需要我们再转通过JSON.parse转一下了,直接可以用 getData(obj) { console.log(obj.name) // wft } } } </script>
这种方式传递参数还是很方便的,我这里方法名写的getData,是因为我的业务里,在点击按钮的时候要拿到webview中的数据,这样我调用webview页面的getData方法,获取到数据然后再通过uni.postMessage传递到uniapp就可以了,也是我接下来要介绍的,webview页面向uniapp传递
三、webview向uniapp传递消息
这个还是需要引入uni中的api,上面也有介绍
<script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.3/index.js"></script>
通过uni.postMessage传递
uni.postMessage({ data: { info: { name: 'wft', age: 18 } } })
这个就很方便了,但是要注意,一定是上面的写法,上面写法我们真正传递的数据是info,data这个对象是必须要写的,官网也有写https://uniapp.dcloud.net.cn/component/web-view.html#web-view
然后在uniapp中监听
//template代码 <web-view :update-title="false" :src="wvSrc" @message="handlerMessage"></web-view> //script代码 // 接受提交参数 handlerMessage(event) { let { info } = event.detail.data[0] console.log(info.name, 'info>>') // wft console.log(info.age, 'info>>') // 18 }
就是这么接收的,很方便。
有一点细节需要注意一下,就是上面代码中我有使用了 // #ifdef APP-PLUS 和 // #endif
这个是判断当前是不是运行在app中的,因为uniapp平时开发调试可以运行在真机上也可以运行在浏览器上的,如果不加 // #ifdef APP-PLUS 和 // #endif 那么运行在浏览器上的时候就会报错了,因为浏览器上是没有this.$scope ,并不用说上面拿webview实例this.$scope.$getAppWebview().children()[0]了,这样可以确保只在运行在真机上的时候才会用那些api。条件编译处理多端差异,这是官网,大家有兴趣可以去瞅瞅
总结
到此这篇关于uniapp使用webview嵌入vue页面及通信实现方式的文章就介绍到这了,更多相关uniapp用webview嵌入vue页面内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!