uniapp webview中实现 app和内嵌的H5双向通信

我们在app的页面中内嵌H5页面的明显好处就是不用频繁的去打包发布,只需要修改h5的页面就可以了

方便是方便, 但麻烦也是真的多, 比如测试的时候,要注意app 和 h5的关系

本次我们主要说的时 两者交互时,用户如何可以同步

首先,我们说一下原理

我们一般是在 app 的页面中, 添加一个 webview 的页面 src 指向我们要加载的 H5 页面就好了。要想让其可以通信,我们采用的是回调的方式

由H5主动来发消息,由app 来接收消息, 再由 app来调用回调函数来返回数据给H5

这里有三个点要清楚,

  1. h5是怎么主动发的消息-> uni.webview.postMessage
  2. app 怎么接收消息 -> <-webview- src="..." @message="handleMessage"><-/web-view>
  3. app把消息返回给h5 -> 回调函数
    由此可见 uni.webview.postMessage是H5用的,所以打包在H5的页面中,
    handleMessage是app中使用的,所以在 app 的包中
    回调函数呢, 它是定义在 H5代码中,却是给 app使用的 webviewObj.evalJS(回调函数)

一般在vue 项目中,我们会在 main.js中 引入

传递的消息信息,必须写在 data 对象中。
event.detail.data 中的数据,以数组的形式接收每次 post 的消息

javascript 复制代码
import * as uni from '@/utils/uni.webview.1.5.6.js'
Vue.prototype.$h5SendToApp = function(action,params, timeout=3000){
	return new Promise((resove,reject)=>{
	//每一次调用这个方法, 我们都来定义一个专用的回调函数
	const callbackName = `app-callback_${Math.random().toSting(36).substr(2,8)}`;
	const timeoutid = setTimeout(()=>{
		if(window[callbackName]){	//如果系统已有这个回调函数,就删除它
			delete window[callbackName]
			// 返回一个错误, 每一次调用的 callbackname都是唯一的才对, 这里报出异常
			reject(new Error(`调用 App action "${action}" 超时(${timeout}ms)`));
		}
	},timeout)

  //如果没有报出异常就创建这个回调函数
  window[callbackName] = (result) => {
		clearTimeout(timeoutid);
		delete window[callbackName];
		resolve(result)
	}
	//**传递的消息信息,必须写在 data 对象中。
	//event.detail.data 中的数据,以数组的形式接收每次 post 的消息**
		uni.webView.postMessage({data:{action,params,callbackName}})  //这里把这次调用对应的回调函数的名称也传过去,方便app端来调用
		//这里要注意参数的格式, 是对象中的data属性
	})
}

当我们在app的页面中,使用了 webview 加载了 h5 的页面时,要获取用户信息, 我们可以调用

javascript 复制代码
this.$h5SendToApp("getUserInfo",{}).then(res=>{
	//这里的罗辑暂时放着
})

有了上面的代码, app端的 @message = "handleMessage" 就会接收到消息

javascript 复制代码
handleMessage(event){
	let paramsInfo = event.detail.data;  //这是可以得到一个数组参数
	//data:{action,params,callbackName} 得到就是这些参数
	//app端的程序 可以根据不同的  action  和 params 来做不同的操作
	//当app 的  action 完成之后, 可能通过 this.$scope.$getAppWebview().children()[0].evalJS(`callbackName(${JSON.stringify(data)})`)
}

this.scope.scope.scope.getAppWebview().children()0.evalJS(callbackName(${JSON.stringify(data)}))

这里说明一下 scope 和 getAppWebview.children()\[\]

uni-app 里 Vue 组件实例 ≠ 页面实例,是两个不同的对象,$scope 就是它们之间的桥。

A**pp 进程里同时存在一大堆 webview: 每个页面一个 webview, 还会再嵌一层子 webview。

this → Vue 组件实例(你写的 data()、methods 都在这,只有 JS 能力)

this.$scope → 页面实例(uni-app 按小程序 Page 规范创建的外壳,持有原生能力)

scope.scope.scope.getAppWebview() → 这个页面所在的原生 webview 对象(plus.webview.WebviewObject,有 evalJS / setStyle / addEventListener)

**

那为什么还要 .children()0

$getAppWebview() 拿到的是页面自己的 webview(外层壳),而我们真正要 evalJS 的是里面那个加载远程 H5 的子 webview。

相关推荐
honkun64 小时前
vue 表格组件 vxe-table 配置 ajax 请求自动加载数据与表单查询
vue.js·vxe-table
kybs19914 小时前
全球灾害数据分析可视化 毕业设计-附源码66794
vue.js·spring boot·mysql·安全·django·c#·asp.net
雪芽蓝域zzs5 小时前
第26章:ECharts 自定义主题 + 页面一键切换主题(深色 / 浅色两套)
vue.js·echars
雪芽蓝域zzs5 小时前
第22章:ECharts 图表联动(多图表交互联动)
vue.js·echars
daols885 小时前
vue 表格组件 vxe-table 实现虚拟滚动与无需滚动加载
vue.js·vxe-table
雪芽蓝域zzs5 小时前
第18章:ECharts 折线图 + 标记点、标记线,自定义 tooltip
vue.js·echars
雪芽蓝域zzs6 小时前
第24章:ECharts 地图组件(基础行政区地图,若依 Vue3)
vue.js·echars
伞伞悦读7 小时前
【第37期】Python JSON 与配置详解:序列化、反序列化、嵌套结构和配置文件
开发语言·python·json
计算机毕设定制辅导-无忧学长7 小时前
《基于Vue的流浪动物救助中心管理系统的设计与实现》
java·vue.js·spring boot·流浪动物救助中心管理系统