uniapp webview大量数据通信

1,019 阅读3分钟

uniapp webview官方地址uniapp.dcloud.net.cn/component/w…
uni.webview.1.5.4.js下载地址 gitee.com/dcloud/uni-…

案例一:原生h5嵌入(这个比较粗略)

注意下面的代码,如果想把静态页面放在app代码一起,静态文件最好放在static文件下,要不然app可能会出错,如下

image.png

留意两个文件的receiveData必须是一致

<template>
  <web-view ref="webview" src="/static/HTML/index.html" @message="handleMessage"></web-view>
</template>
<script setup>
    import { ref } from "vue";
    import { onLoad } from "@dcloudio/uni-app";
    const webview = ref(null);
    const vw = ref(null);
    //----------------------------------------- 获取子应用 发送数据
    function getVw() {
      // 找到路由栈里的最后一位 仅app支持,api见https://uniapp.dcloud.net.cn/tutorial/page.html#getappwebview
      const pages = getCurrentPages();
      vw.value = pages[pages.length - 1].$getAppWebview().children()[0];
      let params = [{
        msg:"这是信息"
      }];
      vw.value.evalJS(`receiveData(${JSON.stringify(params)})`);
    }
    onLoad(() => {
      // 如果是页面初始化调用时,需要延时一下
      setTimeout(() => {
        getVw();
      }, 1000);
    });
    //-------------------------------------------接收数据
    function handleMessage(msg) {}
</script>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"
    />
    <title>啦啦啦</title>
    <script src="./js/uni.webview.1.5.4.js"></script>
    <script src="./css/index.css"></script>
  </head>

  <body>
    <div className="demo">
    </div>
    <script>
      // 接收外层传进来的数据
      function receiveData(data) {
        creatlink("video-container", data);
      }
      //发送数据
      function handleClick () {uni.postMessage({data: {msg: '啦啦啦'}})}
    </script>
  </body>
</html>

案例二:uniapp h5嵌入

<template>
  <web-view
    v-if="src"
    :src="src"
    @message="handleMessage"
    :style="{ 'background-color': safeBg }"
  ></web-view>
</template>
<script setup>
import { ref } from "vue";
import { onShow, onHide, onLoad } from "@dcloudio/uni-app";
const src = ref("");
const wv = ref(null);
let height = 0; //定义动态的高度变量
let statusbar = 0; // 动态状态栏高
onLoad(() => {
  /*#ifdef APP-PLUS*/
    uni.getSystemInfo({
      // 获取当前设备的具体信息
      success: (sysinfo) => {
        // 嵌入页面关闭uniapp的默认导航头部,且本页未开启默认导航头 的情况
        statusbar = sysinfo.statusBarHeight;
        height = sysinfo.windowHeight;
        // 嵌入页面开启uniapp默认导航头部的情况,且本页开启默认导航头 的情况
        // 这样可以做到单独访问嵌入页也能有导航头
        // statusbar = sysinfo.statusBarHeight;
        // height = sysinfo.windowHeight + sysinfo.windowHeight;
      },
    });
    //这里一定要延迟
    setTimeout(() => {
      const pages = getCurrentPages();
      wv.value = pages[pages.length - 1].$getAppWebview().children()[0];
      //给嵌入页发送信息
      wv.value.evalJS(
        `receiveData(${JSON.stringify({
          msg: "哈哈哈哈哈哈哈哈哈哈哈哈哈",
        })})`
      );
      wv.value.setStyle({
        top: statusbar,
        height: height,
      });
    }, 1000);
    //监听软键盘出现
    if(plus.os.name !== "iOS"){
        uni.onKeyboardHeightChange((res) => {
          if (res.height == 0) {
            wv.value.setStyle({
              top: statusbar,
              height: height,
            });
          } else {
            wv.value.setStyle({
              top: statusbar ,
              height: height - res.height,
            })
          }
        });
    }
  /*#endif*/
  
  src.value = `这是嵌入的H5地址?token=11111`;
  console.log(src.value);

  /*#ifdef H5*/
  window.addEventListener("message", handleMessage, false);
  /*#endif*/
});
onShow(() => {
  if (wv.value) {
    //给嵌入页发送信息
    wv.value.evalJS(
      `receiveData(${JSON.stringify({
        msg: "哈哈哈哈哈哈哈哈哈哈哈哈哈",
      })})`
    );
  }
});

const safeBg = ref("#fff");
function handleMessage(msg) {
  // console.log("收到消息————————————————————————", msg);
  let getdata;
  /*#ifdef APP-PLUS*/
  getdata = msg.detail.data[0];
  /*#endif*/
  /*#ifdef H5*/
  getdata = msg.data.data.arg;
  /*#endif*/
  console.log("web-view收到消息", getdata.msg);
  //这里举例几个很常用的场景
  //多见于嵌入页内还要切换的场景 或
  //嵌入页的导航头为自定义(需要修改上面空出来安全距离的颜色)
  switch (getdata.msg) {
    case "tabbar隐藏":
      uni.hideTabBar({
        animation: true,
      });
      /*#ifdef APP-PLUS*/
      wv.value.setStyle({
        top: statusbar,
        height: height
      });
      /*#endif*/
      break;
    case "tabbar出现":
      uni.showTabBar({
        animation: true,
      });
      /*#ifdef APP-PLUS*/
      wv.value.setStyle({
        top: statusbar,
        height: height - 50,//tabbar的默认高度为50
      });
      /*#endif*/
      break;
    case "改变顶部安全距离颜色":
      safeBg.value = getdata.color;
      break;
    default:
      break;
  }
}
onHide(() => {
  // #ifdef APP-PLUS
  // 取消监听键盘高度
  uni.offKeyboardHeightChange((res) => {});
  // #endif
});
</script>
<style scoped lang="scss"></style>

嵌入页代码的App.vue中,加入如下代码

<script>
export default {
  onLaunch: function () {
    console.log("WEB onLaunch", location.href);
    //不需要登录的页面
    const white = ["/pages/PrivacyAgreement/index"]
    if (white.includes(location.href.split('#')[1])) {
      return
    }
    //需要登录的页面
    function getUrlKey(name, url) {
      let getdata =
        decodeURIComponent(
          (new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec(
            url
          ) || [, ""])[1].replace(/\+/g, "%20")
        ) || undefined;
      if (getdata == "undefined" || getdata == undefined) {
        return "";
      }
      return getdata;
    }
    // 设置token,权限获取
    const token = getUrlKey("token", location.href);
    if (token) {
      console.log("取到token为",token);
      // 取到token,设置本地存储和状态存储
    } else {
      //为什么要这么做,因为如果杀后台的话,到子页面就成了第一页无法再次返回,再做返回的处理很麻烦,干脆手动返回首页
      uni.reLaunch({
        url: "/pages/index/index",
      });
    }
  },
  onShow: function () {},
  onHide: function () {},
};
window.receiveData = function (data) {
  console.log("接收外层传进来的数据", data.msg);
  //接收数据,刷新数据等操作
};
</script>

如果嵌入页想向父页发送消息,如下,至于为什么是webuni.而不是uni.见最下面的注意
这个引入一定要在入口文件main.js引入,要不然打包会报错(webuni 找不到)

import '@/utils/uni.webview.1.5.4.js'
webuni.postMessage({data: {msg: '啦啦啦'}})

注意!!!!

①语言平台差异

如果web页面是uniapp开发的,那么uni.webview.1.5.4.js这个文件需要修改,将以下3个地方的uni改成你习惯的,如webuni,如下图

image.png

image.png 然后使用是将 如uni.postMessage({data: {msg: '啦啦啦'}})改成 webuni.postMessage({data: {msg: '啦啦啦'}})

②H5和app平台差异

Ⅰ、网页调试时,<web-view ref="webview" src="/static/HTML/index.html" @message="handleMessage"></web-view>中的@message是不生效的,要使用window.addEventListener("message", handleMessage, false); 文档来源developer.mozilla.org/zh-CN/docs/…

Ⅱ、function handleMessage(msg) {}这个代码中,H5和app返回的msg是不一样的,具体自己调试看看