> 技术文档 > uniapp实现与webview之间的相互通讯_uniapp webview通信

uniapp实现与webview之间的相互通讯_uniapp webview通信

基于uniapp开发在一些特殊场景,可能会用到app嵌套h5或h5嵌套h5的场景,uniapp中有一个web-view组件类似于iframe我们可以基于web-view实现双向通信,以下是对不同情况下的使用总结:

写在最前面:

  1. uniapp开发的app嵌套h5时必须是.nvue文件否则没有这个sWebViewRef.value.evalJs函数
  2. uni.webview.js只需要在嵌套的h5中引入

情况一:app嵌套h5(app、h5均用uniapp开发)

在正式使用前要先在嵌套的h5中中引入uni.webview.1.5.6.js以1.5.6举例,文件可能已更新,最新请移步uni.webview.js 最新版地址下载

下载完成后,我们只需要在h5项目main.js中进行引入

// main.jsimport \'./uni_web_view_1.5.6.js\'

引入完成后我们在h5项目中任意文件下打印uni会发现在uni上多了一个webView,打印uni.webView会发现他是一个对象,并有如下方法:

navigateBack、navigateTo、reLaunch、redirectTo、switchTab、getEnv、postMessage

上述方法相信作为uni开发者大家并不陌生,这里只着重讲解:getEnv、postMessage

h5向app发送消息

  // getEnv 获取当前环境 uni.webView.getEnv((res) => { console.log(\'当前环境:\' + JSON.stringify(res)); }) // postMessage 向应用发送消息 const postMsg = () => { uni.webView.postMessage({ data: { msg: \'哈哈哈\', }, }) }   import { ref, onMounted } from \'vue\' // nvue文件不能使用100vw,100vh const systemInfo = uni.getSystemInfoSync() const webviewStyles = ref({ width: \'\', height: \'\', }) webviewStyles.value.width = systemInfo.windowWidth + \'px\' webviewStyles.value.height = systemInfo.windowHeight + \'px\' const sWebViewRef = ref() // h5地址,这里临时写死实际项目自行根据环境判断 const url = ref(\'http://192.168.110.128:7189/\') // 接收内容: const handleWebViewMessage = (event) => { console.log(\'handleWebViewMessage\', event) const [noWEBData] = event.detail.data console.log(\'noWEBData\', noWEBData) }

上面我们实现了在h5中向app中发送信息,那app如何向h5中发送信息呢?

   import { ref, onMounted } from \'vue\' const sWebViewRef = ref() // h5地址,这里临时写死实际项目自行根据环境判断 const url = ref(\'http://192.168.110.128:7189/\') // 接收内容: const handleWebViewMessage = (event) => { console.log(\'handleWebViewMessage\', event) const [noWEBData] = event.detail.data console.log(\'noWEBData\', noWEBData) } const test = ref(\'嘻嘻嘻\') onMounted(() => { setInterval(() => { sWebViewRef.value.evalJs(`x_sun(\'${test.value}\')`) }, 2000) })  // getEnv 获取当前环境 uni.webView.getEnv((res) => { console.log(\'当前环境:\' + JSON.stringify(res)); }) // postMessage 向应用发送消息 const postMsg = () => { uni.webView.postMessage({ data: { msg: \'哈哈哈\', }, }) } window.x_sun = (e) => { console.log(\'x_sun\', e) }

情况二:app嵌套h5(h5用vue或react开发)

上述情况一中讲到了要引用uni.webview,在这里我默认你已经看了如何在嵌套h5中引入uni.webview.js

引入完成后我们在h5项目中任意文件下打印uni会发现他是一个对象,并有如下方法:

navigateBack、navigateTo、reLaunch、redirectTo、switchTab、getEnv、postMessage

上述方法在情况一中已有案例便不再复述

情况三:h5嵌套h5(均用uniapp开发)

为了方便理解我将外层h5称之为父级,嵌套的内层h5称之为子级

上述情况一中讲到了要引用uni.webview,在这里我默认你已经看了如何在嵌套h5中引入uni.webview.js

引入完成后我们在h5项目中任意文件下打印uni会发现他是一个对象,并有如下方法:

navigateBack、navigateTo、reLaunch、redirectTo、switchTab、getEnv、postMessage

子级h5向父级h5发送消息

  // getEnv 获取当前环境 uni.getEnv((res) => { console.log(\'当前环境:\' + JSON.stringify(res)); }) // postMessage 向父级发送消息 const postMsg = () => { uni.postMessage({ data: { msg: \'哈哈哈\', }, }) }   import { ref, onMounted } from \'vue\' // nvue文件不能使用100vw,100vh const systemInfo = uni.getSystemInfoSync() const webviewStyles = ref({ width: \'\', height: \'\', }) webviewStyles.value.width = systemInfo.windowWidth + \'px\' webviewStyles.value.height = systemInfo.windowHeight + \'px\' const sWebViewRef = ref() // h5地址,这里临时写死实际项目自行根据环境判断 const url = ref(\'http://192.168.110.128:7189/\') // 接收内容: const handleWebViewMessage = (event) => { console.log(\'handleWebViewMessage\', event) const { data: webData } = event.data console.log(\'webData\', webData) } // h5通过对message添加侦听事件,监听嵌套h5中发送的内容 window.addEventListener(\'message\', handleWebViewMessage)

上面我们实现了在子级h5中向父级h5中发送信息,那父级h5如何向子级h5中发送信息呢?

   import { ref, onMounted } from \'vue\' const sWebViewRef = ref() // h5地址,这里临时写死实际项目自行根据环境判断 const url = ref(\'http://192.168.110.128:7189/\') // 接收内容: const handleWebViewMessage = (event) => { console.log(\'handleWebViewMessage\', event) const [noWEBData] = event.detail.data console.log(\'noWEBData\', noWEBData) } const test = ref(\'嘻嘻嘻\') const sWebViewEl = ref() onMounted(() => { sWebViewEl.value = document.getElementById(\'sWebView\').contentWindow setInterval(() => { sWebViewEl.contentWindow.postMessage({ fn: \'x_sun\', arg: test.value }, \'*\') // 也可手动指定我要向这个子级发送信息 // sWebViewEl.contentWindow.postMessage({ fn: \'x_sun\', arg: test.value }, \'http://192.168.110.128:7189\') }, 2000) })  // getEnv 获取当前环境 uni.webView.getEnv((res) => { console.log(\'当前环境:\' + JSON.stringify(res)); }) // postMessage 向应用发送消息 const postMsg = () => { uni.webView.postMessage({ data: { msg: \'哈哈哈\', }, }) } window.x_sun = (e) => { console.log(\'x_sun\', e) } const handleWebViewMessage = (event) => { event.data.fn && window[event.data.fn](event.data.arg) } window.addEventListener(\'message\', handleWebViewMessage)

如若需要既需要兼容app嵌套h5又需要兼容h5嵌套h5可以在父级的app或h5页面中通过uniapp中的条件编译进行判断,参考代码:

 import { ref, onMounted } from \'vue\' import { useWebView } from \'./hooks/useWebView\' import { useNoWebView } from \'./hooks/useNoWebView\' const { webMessageMap } = useWebView() const { noWebMessageMap } = useNoWebView() const sWebViewRef = ref() const url = ref(\'http://192.168.110.128:7189/\') const systemInfo = uni.getSystemInfoSync() const webviewStyles = ref({ width: \'\', height: \'\', }) webviewStyles.value.width = systemInfo.windowWidth + \'px\' webviewStyles.value.height = systemInfo.windowHeight + \'px\' const handleWebViewMessage = (event) => { // #ifdef WEB const { data: webData } = event.data webData?.name && (webMessageMap[webData.name] ? webMessageMap[webData.name](webData.arg) : webMessageMap.default(webData.arg)) // #endif // #ifndef WEB const [noWEBData] = event.detail.data console.log(\'noWEBData\', noWEBData) noWebMessageMap[event.type] ? noWebMessageMap[event.type](noWEBData) : noWebMessageMap.default(noWEBData) // #endif } const test = ref(\'嘻嘻嘻\') const sWebViewEl = ref() // #ifdef WEB onMounted(() => { sWebViewEl.value = document.getElementById(\'sWebView\').contentWindow setInterval(() => { sWebViewEl.value.postMessage({ fn: \'x_sun\', arg: test.value }, \'*\') // sWebViewEl.contentWindow.postMessage({ name: \'x_sun\', arg: test.value }, \'http://192.168.110.128:7189\') }, 2000) }) // #endif // #ifndef WEB onMounted(() => { setInterval(() => { sWebViewRef.value.evalJs(`x_sun(\'${test.value}\')`) }, 2000) }) // #endif // #ifdef WEB window.addEventListener(\'message\', handleWebViewMessage) // #endif    

参考文献:

web-view | uni-app官网

在web-view加载的本地及远程HTML中调用uni的API及网页和vue页面通讯