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

打印 上一主题 下一主题

主题 862|帖子 862|积分 2586

基于uniapp开发在一些特别场景,可能会用到app嵌套h5或h5嵌套h5的场景,uniapp中有一个web-view组件类似于iframe我们可以基于web-view实现双向通讯,以下是对不同环境下的利用总结:
写在最前面:

  • uniapp开发的app嵌套h5时必须是.nvue文件否则没有这个sWebViewRef.value.evalJs函数
  • 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中进行引入
  1. // main.js
  2. import './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发送消息
  1. <!-- h5 -->
  2. <template>
  3.    <button @click="postMsg">向应用发送信息</button>
  4. </template>
  5. <script setup>
  6.   // getEnv 获取当前环境
  7.   uni.webView.getEnv((res) => {
  8.     console.log('当前环境:' + JSON.stringify(res));
  9.   })
  10.   // postMessage 向应用发送消息
  11.   const postMsg = () => {
  12.     uni.webView.postMessage({
  13.       data: {
  14.         msg: '哈哈哈',
  15.       },
  16.     })
  17.   }
  18. </script>
  19. <!-- h5通过postMessage像app发送信息,app如何接收?创建.nvue文件,并编写如下代码: -->
  20. <!-- app -->
  21. <template>
  22.   <web-view ref="sWebViewRef" id="sWebView" :style="webviewStyles" :src="url" @onPostMessage="handleWebViewMessage" @message="handleWebViewMessage">
  23.   </web-view>
  24. </template>
  25. <script setup>
  26.   import { ref, onMounted } from 'vue'
  27.   // nvue文件不能使用100vw,100vh
  28.   const systemInfo = uni.getSystemInfoSync()
  29.   const webviewStyles = ref({
  30.     width: '',
  31.     height: '',
  32.   })
  33.   webviewStyles.value.width = systemInfo.windowWidth + 'px'
  34.   webviewStyles.value.height = systemInfo.windowHeight + 'px'
  35.   const sWebViewRef = ref()
  36.   // h5地址,这里临时写死实际项目自行根据环境判断
  37.   const url = ref('http://192.168.110.128:7189/')
  38.   // 接收内容:
  39.   const handleWebViewMessage = (event) => {
  40.     console.log('handleWebViewMessage', event)
  41.     const [noWEBData] = event.detail.data
  42.     console.log('noWEBData', noWEBData)
  43.   }
  44. </script>
复制代码
上面我们实现了在h5中向app中发送信息,那app怎样向h5中发送信息呢?
  1. <!-- app -->
  2. <template>
  3.   <web-view ref="sWebViewRef" id="sWebView" :style="webviewStyles" :src="url" @onPostMessage="handleWebViewMessage" @message="handleWebViewMessage">
  4.   </web-view>
  5. </template>
  6. <script setup>
  7.   import { ref, onMounted } from 'vue'
  8.   const sWebViewRef = ref()
  9.   // h5地址,这里临时写死实际项目自行根据环境判断
  10.   const url = ref('http://192.168.110.128:7189/')
  11.   // 接收内容:
  12.   const handleWebViewMessage = (event) => {
  13.     console.log('handleWebViewMessage', event)
  14.     const [noWEBData] = event.detail.data
  15.     console.log('noWEBData', noWEBData)
  16.   }
  17.   const test = ref('嘻嘻嘻')
  18.   onMounted(() => {
  19.     setInterval(() => {
  20.       sWebViewRef.value.evalJs(`x_sun('${test.value}')`)
  21.     }, 2000)
  22.   })
  23. </script>
  24. <!-- h5 -->
  25. <template>
  26.    <button @click="postMsg">向应用发送信息</button>
  27. </template>
  28. <script setup>
  29.   // getEnv 获取当前环境
  30.   uni.webView.getEnv((res) => {
  31.     console.log('当前环境:' + JSON.stringify(res));
  32.   })
  33.   // postMessage 向应用发送消息
  34.   const postMsg = () => {
  35.     uni.webView.postMessage({
  36.       data: {
  37.         msg: '哈哈哈',
  38.       },
  39.     })
  40.   }
  41.   window.x_sun = (e) => {
  42.     console.log('x_sun', e)
  43.   }
  44. </script>
复制代码
环境二: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发送消息
  1. <!-- 子级h5 -->
  2. <template>
  3.    <button @click="postMsg">向父级发送信息</button>
  4. </template>
  5. <script setup>
  6.   // getEnv 获取当前环境
  7.   uni.getEnv((res) => {
  8.     console.log('当前环境:' + JSON.stringify(res));
  9.   })
  10.   // postMessage 向父级发送消息
  11.   const postMsg = () => {
  12.     uni.postMessage({
  13.       data: {
  14.         msg: '哈哈哈',
  15.       },
  16.     })
  17.   }
  18. </script>
  19. <!-- 子级通过postMessage向父级发送信息,父级如何接收? -->
  20. <!-- 父级h5 -->
  21. <template>
  22.   <web-view ref="sWebViewRef" id="sWebView" :style="webviewStyles" :src="url" @onPostMessage="handleWebViewMessage" @message="handleWebViewMessage">
  23.   </web-view>
  24. </template>
  25. <script setup>
  26.   import { ref, onMounted } from 'vue'
  27.   // nvue文件不能使用100vw,100vh
  28.   const systemInfo = uni.getSystemInfoSync()
  29.   const webviewStyles = ref({
  30.     width: '',
  31.     height: '',
  32.   })
  33.   webviewStyles.value.width = systemInfo.windowWidth + 'px'
  34.   webviewStyles.value.height = systemInfo.windowHeight + 'px'
  35.   const sWebViewRef = ref()
  36.   // h5地址,这里临时写死实际项目自行根据环境判断
  37.   const url = ref('http://192.168.110.128:7189/')
  38.   // 接收内容:
  39.   const handleWebViewMessage = (event) => {
  40.     console.log('handleWebViewMessage', event)
  41.     const { data: webData } = event.data
  42.     console.log('webData', webData)
  43.   }
  44.   // h5通过对message添加侦听事件,监听嵌套h5中发送的内容
  45.   window.addEventListener('message', handleWebViewMessage)
  46. </script>
复制代码
上面我们实现了在子级h5中向父级h5中发送信息,那父级h5怎样向子级h5中发送信息呢?
  1. <!-- 父级h5 -->
  2. <template>
  3.   <web-view ref="sWebViewRef" id="sWebView" :style="webviewStyles" :src="url" @onPostMessage="handleWebViewMessage" @message="handleWebViewMessage">
  4.   </web-view>
  5. </template>
  6. <script setup>
  7.   import { ref, onMounted } from 'vue'
  8.   const sWebViewRef = ref()
  9.   // h5地址,这里临时写死实际项目自行根据环境判断
  10.   const url = ref('http://192.168.110.128:7189/')
  11.   // 接收内容:
  12.   const handleWebViewMessage = (event) => {
  13.     console.log('handleWebViewMessage', event)
  14.     const [noWEBData] = event.detail.data
  15.     console.log('noWEBData', noWEBData)
  16.   }
  17.   const test = ref('嘻嘻嘻')
  18.   const sWebViewEl  = ref()
  19.   onMounted(() => {
  20.     sWebViewEl.value = document.getElementById('sWebView').contentWindow
  21.     setInterval(() => {
  22.       sWebViewEl.contentWindow.postMessage({ fn: 'x_sun', arg: test.value }, '*')
  23.       // 也可手动指定我要向这个子级发送信息
  24.       // sWebViewEl.contentWindow.postMessage({ fn: 'x_sun', arg: test.value }, 'http://192.168.110.128:7189')
  25.     }, 2000)
  26.   })
  27. </script>
  28. <!-- 子级h5 -->
  29. <template>
  30.    <button @click="postMsg">向应用发送信息</button>
  31. </template>
  32. <script setup>
  33.   // getEnv 获取当前环境
  34.   uni.webView.getEnv((res) => {
  35.     console.log('当前环境:' + JSON.stringify(res));
  36.   })
  37.   // postMessage 向应用发送消息
  38.   const postMsg = () => {
  39.     uni.webView.postMessage({
  40.       data: {
  41.         msg: '哈哈哈',
  42.       },
  43.     })
  44.   }
  45.   window.x_sun = (e) => {
  46.     console.log('x_sun', e)
  47.   }
  48.   const handleWebViewMessage = (event) => {
  49.    event.data.fn && window[event.data.fn](event.data.arg)
  50.   }
  51.   window.addEventListener('message', handleWebViewMessage)
  52. </script>
复制代码
如若需要既需要兼容app嵌套h5又需要兼容h5嵌套h5可以在父级的app或h5页面中通过uniapp中的条件编译进行判定,参考代码:
  1. <script setup>
  2.   import { ref, onMounted } from 'vue'
  3.   import { useWebView } from './hooks/useWebView'
  4.   import { useNoWebView } from './hooks/useNoWebView'
  5.   const { webMessageMap } = useWebView()
  6.   const { noWebMessageMap } = useNoWebView()
  7.   const sWebViewRef = ref()
  8.   const url = ref('http://192.168.110.128:7189/')
  9.   const systemInfo = uni.getSystemInfoSync()
  10.   const webviewStyles = ref({
  11.     width: '',
  12.     height: '',
  13.   })
  14.   webviewStyles.value.width = systemInfo.windowWidth + 'px'
  15.   webviewStyles.value.height = systemInfo.windowHeight + 'px'
  16.   const handleWebViewMessage = (event) => {
  17.     // #ifdef WEB
  18.     const { data: webData } = event.data
  19.     webData?.name && (webMessageMap[webData.name] ? webMessageMap[webData.name](webData.arg) : webMessageMap.default(webData.arg))
  20.     // #endif
  21.     // #ifndef WEB
  22.     const [noWEBData] = event.detail.data
  23.     console.log('noWEBData', noWEBData)
  24.     noWebMessageMap[event.type] ? noWebMessageMap[event.type](noWEBData) : noWebMessageMap.default(noWEBData)
  25.     // #endif
  26.   }
  27.   const test = ref('嘻嘻嘻')
  28.   const sWebViewEl = ref()
  29.   // #ifdef WEB
  30.   onMounted(() => {
  31.     sWebViewEl.value = document.getElementById('sWebView').contentWindow
  32.     setInterval(() => {
  33.       sWebViewEl.value.postMessage({ fn: 'x_sun', arg: test.value }, '*')
  34.       // sWebViewEl.contentWindow.postMessage({ name: 'x_sun', arg: test.value }, 'http://192.168.110.128:7189')
  35.     }, 2000)
  36.   })
  37.   // #endif
  38.   // #ifndef WEB
  39.   onMounted(() => {
  40.     setInterval(() => {
  41.       sWebViewRef.value.evalJs(`x_sun('${test.value}')`)
  42.     }, 2000)
  43.   })
  44.   // #endif
  45.   // #ifdef WEB
  46.   window.addEventListener('message', handleWebViewMessage)
  47.   // #endif
  48. </script>
  49. <template>
  50.   <view>
  51.     <web-view ref="sWebViewRef" id="sWebView" :style="webviewStyles" :src="url" @onPostMessage="handleWebViewMessage" @message="handleWebViewMessage">
  52.     </web-view>
  53.   </view>
  54. </template>
  55. <style></style>
复制代码
参考文献:
web-view | uni-app官网
在web-view加载的当地及长途HTML中调用uni的API及网页和vue页面通讯

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

罪恶克星

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表