网络日志

uni-app app端web-view通信

本文简介

点赞 + 关注 + 收藏 = 学会了

uni-app 或者 微信小程序 中,都有 web-view 组件。

该组件是一个浏览器组件,可以承载网页的内容。而且该组件是全屏的,会覆盖该组件之外的其他内容。

本文要讲解在 uni-app 中使用 web-view 怎么实现大量数据通信。

我所使用的是 Vue 3 语法。

web-view 数据通信方法

web-view 文档

web-view 其实有点像 iframe ,但在 uni-app 又提供了几种基础的通信方式。

基础用法可以看文档,本文主要讲解如何在 主应用web-view 传输数据。

本案例目录结构

省略部分目录

- hybrid
|- html
 |- js
  |- uni.webview.1.5.3.js
 |-index.html
- pages
 |- index
  |- index.vue

父传子

我们暂定,主应用web-view 的页面为

“父传子” 的方式有2种:

  1. 通过 url 传值
  2. 使用 uni.webview.js

1、通过 url 传值

数据量少的话,可以通过 url 的方式传给子应用。

index.vue

<template>
  <view class="content">
    <web-view
        src="/hybrid/html/index.html?msg=hello"
    ></web-view>
  </view>
</template>

这种方法的优点是简单,缺点是传输的数据量有限,而且基本传输的都是字符串。

2、使用 uni.webview.js 传值

本文使用的是 uni.webview.1.5.3.js ,在阅读本文时可能官方已经更新了新版。

你可以在 web-view 文档 里,滑到“注意事项”里面找到最新版的下载地址

主应用 /pages/index/index.vue

<template>
  <view class="content">
    <web-view
      ref="webview"
      src="/hybrid/html/index.html"
      @message="handleMessage"
    ></web-view>
  </view>
</template>

<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'

const webview = ref(null)

const pages = getCurrentPages()

const vw = ref(null)

// 获取子应用
function getVw() {
  // 找到路由栈里的最后一位
  vw.value = pages[pages.length - 1].$getAppWebview().children()[0]

  // 使用 evalJS 方法,调用子应用里的事件
  // receiveData 是在子应用里定义的事件
  // 最后需要注意,evalJS 传入的是一个字符串。
  vw.value.evalJS("receiveData({msg: '雷猴啊'})")
}

onLoad(() => {
  // 如果是页面初始化调用时,需要延时一下
  setTimeout(() => {
    getVw()
  }, 1000)
})
</script>

子应用 /hybrid/html/index.html

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>web-view</title>
</head>
<body>
  <!-- 引入 uni.webview.js -->
  <script src="./js/uni.webview.1.5.3.js"></script>
  <script>
    // 接收外层传进来的数据
    function receiveData(data) {
      console.log(JSON.stringify(data))
    }
  </script>
</body>
</html>

这么简单就实现了大量数据的传输,而且还可以传对象等数据。

最后需要注意的是,子应用定义接收数据的方法名,要跟主应用调用时一致。

比如本例定义的方法名为 receiveData

子传父

子应用要向主应用传值,uni-app 官方就提供了方法 @message

主应用 /pages/index/index.vue

<template>
  <view class="content">
    <web-view
      src="/hybrid/html/index.html"
      @message="handleMessage"
    ></web-view>
  </view>
</template>

<script setup>
import { ref } from 'vue'

// 接受 webview 传递过来的数据
function handleMessage(msg) {
  console.log(msg)
}
</script>

子应用 /hybrid/html/index.html

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>web-view</title>
</head>
<body>
  <div>
    <button onclick="handleClick()">向上传递数据</button>
  </div>
    
  <script src="./js/uni.webview.1.5.3.js"></script>
  <script>
    // 向外传递数据,数据要放在data里
    function handleClick () {
      uni.postMessage({
        data: {
          msg: '雷猴'
        }
      })
    }
  </script>
</body>
</html>

此时在页面上点击按钮,主应用就会接收到子应用传过来的数据。

除了 @message 外,uni-app 还提供了很多方法和属性可以调用。

方法

方法名说明平台差异说明
uni.navigateTonavigateTo
uni.redirectToredirectTo
uni.reLaunchreLaunch
uni.switchTabswitchTab
uni.navigateBacknavigateBack
uni.postMessage向应用发送消息字节跳动小程序不支持、H5 暂不支持(可以直接使用 window.postMessage (opens new window)
uni.getEnv获取当前环境字节跳动小程序与飞书小程序不支持

属性

属性名类型说明平台差异说明
srcStringwebview 指向网页的链接
allowString用于为 iframe (opens new window)指定其特征策略(opens new window)H5
sandboxString该属性对呈现在 iframe (opens new window)框架中的内容启用一些额外的限制条件。H5
webview-stylesObjectwebview 的样式App-vue
update-titleBoolean是否自动更新当前页面标题。默认值:trueApp-vue (HBuilder X 3.3.8+)
@messageEventHandler网页向应用 postMessage 时,会在特定时机(后退、组件销毁、分享)触发并收到消息。H5 暂不支持(可以直接使用 window.postMessage (opens new window)
@onPostMessageEventHandler网页向应用实时 postMessageApp-nvue

以上官方提供的方法和属性建议你都尝试一遍,都是非常简单的。

推荐阅读

👍《『uni-app、小程序』蓝牙连接、读写数据全过程》

👍《uni-app App端半屏连续扫码》

👍《Vue3 过10种组件通讯方式》点赞 + 关注 + 收藏 = 学会了