uniapp web-view 页面通讯

1,484 阅读2分钟

在最近的项目开发使用过程中发现因为需要传递的参数太多导致web-viwesrc参数超长,页面加载失败。最终选择的解决方案为uniapp中的postMessage来实现通讯。uni.postMessage

app 端页面分为.vue.nvue两种类型的文件,获取web-view的方式存在一定差异,即为: $scope.$getAppWebview().children()[0]$refs.webView

而在接收消息时也有一定差异,分别为@message@onPostMessage

vuenvue编译为H5都是相同的写法,不存在差异。

vue 内容

<template>
  <web-view src="src" @message="handlerPostMessage"/>
</template>

<script>
export default {
  data() {
    return {
      webView: null,
      origin: null,
    };
  },
  onReady() {
    // #ifdef APP-PLUS
    // 获取当前页面的webview对象
    const currentWebview = this.$scope.$getAppWebview();
    // 如果是页面初始化调用时,需要延时一下
    setTimeout(() => {
      this.webView = currentWebview.children()[0];
    }, 1000); 
    // #endif
  },
  mounted() {
    // #ifdef H5
    window.addEventListener('message', (e) => {
      if (e.origin !== window.location.origin) {
        this.webView = e.source;
        this.origin = e.origin;
        console.log(e.data,'HTML 接受H5端发送过来的消息');
      }
    }, false);
    // #endif
  },
  methods: {
    /**
     * 接收消息
     */
    handlerPostMessage(data) {
      console.log('接收来自 html 页面的消息 ::> ', data);
    },

    /**
     * APP
     * 直接调用 html 页面中的方法
     */
    sendMessage() {
      cosnt params = JSON.stringify(params);
      this.webView.evalJS(`receiveMessage(${parmas})`);
    },

    /**
     * H5
     * 监听来自 html 页面的消息,并向来源发送一条消息
     * 注:需要目标的源才能向目标发送消息
     * 即:需要 html 向 H5 发送消息之后,H5 才能向 hmtl 发送消息
     */
    sendMessage() {
      const params = {a: 1, b: 2, c: 3};
      this.webView.postMessage(params, this.origin);
    },
  }
}
</script>

nvue 内容

<template>
  <web-view ref="webView" src="src" @onPostMessage="handlerPostMessage"/>
</template>

<script>
export default {
  data() {
    return {
      webView: null,
      origin: null,
    };
  },
  mounted() {
    // #ifdef H5
    window.addEventListener('message', (e) => {
      if (e.origin !== window.location.origin) {
        this.webView = e.source;
        this.origin = e.origin;
        console.log(e.data,'HTML 接受H5端发送过来的消息');
      }
    }, false);
    // #endif
  },
  methods: {
    /**
     * 接收消息
     */
    handlerPostMessage(data) {
      console.log('接收来自 html 页面的消息 ::> ', data);
    },

    /**
     * APP
     * 直接调用 HTML 页面中的方法
     */
    sendMessage() {
      cosnt params = JSON.stringify(params);
      this.$refs.webView.evalJS(`receiveMessage(${parmas})`);
    },

    /**
     * H5
     * 监听来自 HTML 页面的消息,并向来源发送一条消息
     * 注:需要目标的源才能向目标发送消息
     * 即:需要 HTML 向 H5 发送消息之后,H5 才能向 HTML 发送消息
     */
    sendMessage() {
      const params = {a: 1, b: 2, c: 3};
      this.webView.postMessage(params, this.origin);
    },
  }
}
</script>

html 内容

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
    <title>网络网页</title>
    <style type="text/css">
      .btn {
        display: block;
        margin: 20px auto;
        padding: 5px;
        background-color: #007aff;
        border: 0;
        color: #ffffff;
        height: 40px;
        width: 200px;
      }

      .btn-red {
        background-color: #dd524d;
      }

      .btn-yellow {
        background-color: #f0ad4e;
      }

      .desc {
        padding: 10px;
        color: #999999;
      }
    </style>
  </head>
  <body>
    <p class="desc">web-view 组件加载网络 html 示例。点击下列按钮,跳转至其它页面。</p>
    <div class="post-message-section">
      <p class="desc">网页向应用发送消息,注意:小程序端应用会在此页面后退时接收到消息。</p>
      <div class="btn-list">
        <button class="btn btn-red" type="button" id="postMessage">postMessage</button>
      </div>
    </div>
    <!-- uni 的 SDK -->
    <!-- 需要把 uni.webview.1.5.4.js 下载到自己的服务器 -->
    <script type="text/javascript" src="https://unpkg.com/@dcloudio/uni-webview-js@0.0.3/index.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/vConsole/3.14.7/vconsole.min.js"></script>
    <script type="text/javascript">
       // 初始化
      var vConsole = new VConsole();
        // 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。
      document.addEventListener('UniAppJSBridgeReady', function() {
        uni.getEnv(function(res) {
            console.log('当前环境:' + JSON.stringify(res));
        });

        document.getElementById('postMessage').addEventListener('click', function() {
          uni.postMessage({
            data: {
              action: 'message'
            }
          });
        });
      });

      // HTML 接受H5端发送过来的消息
      window.addEventListener('message', e => {
        console.log('e.origin', e.origin);
        console.log('window.location.origin', window.location.origin);
        if (e.origin !== window.location.origin) {
          console.log(e.data,'HTML 接受H5端发送过来的消息');
        }
      }, false)

      // HTML 接受APP发送过来的消息
      function receiveMessage (data) {
        alert('receiveMessage');
        console.log(JSON.stringify(data),'HTML 接受APP发送过来的消息');
      }
    </script>
  </body>
</html>