uniapp(H5 和 App) 与 Web 端,完整代码,真正解决通信问题

本文详细介绍了如何在uniapp中使用web-view组件嵌入网页,并处理了webview与H5页面之间的通信,包括设置webview高度、使用postMessage传递数据以及JavaScript注入技术evalJS的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先去官网了解下webview web-view | uni-app官网 (dcloud.net.cn)

uniapp

1.要嵌入 webview 的 index.vue 文件

<template>
	<view>
		<web-view :src="reportSrc" :webview-styles="webviewStyles" :update-title="false" @message="message"></web-view>
		<!-- 如果要在当前已经嵌入webview文件的页面加按钮的话,需要调整webview的高度,因为默认是撑满整个页面 -->
		<button style="position: fixed;bottom: 0;width: 100%;" type="primary" @click="submit">发送打印请求</button>
	</view>
</template>

<script>
	//计划创建的webview(必须写,否则会报错)
	var wv;
	export default {
		data() {
			return {
				// 调整webview页面的高度为85%,这样固定在页面底部的按钮就可以显示出来了
				webviewStyles: {
					width: '100%',
					height: '85%'
				},
				// 要嵌入的web页面地址
				reportSrc: '',
			};
		},
		created() {
			// web端的网页地址(如果是本地跑的 html 的话需要使用 vscode中的 live server 打开该 html 文件
			// 然后你发现那个 html文件的地址是 http://127.0.0.1:5500/index.html , 这个地址需要替换成当前电脑的 ip地址 如 192.166.66.117
			// 最后 webview 引用的网页地址是 http://192.166.66.117:5500/,很多的答案都直接忽略了这里,导致我尝试了很多次在手机上都不成功!
			this.reportSrc = `http://192.166.66.117:5500/`
		},
		onLoad() {
			// App端
			// #ifdef APP-PLUS
			//此对象相当于html5plus里的plus.webview.currentWebview()。在uni-app里vue页面直接使用plus.webview.currentWebview()无效
			uni.showLoading({
				title: '加载中'
			});
			var currentWebview = this.$scope.$getAppWebview()
			setTimeout(function() {
				wv = currentWebview.children()[0]
				uni.hideLoading()
			}, 1000); //如果是页面初始化调用时,需要延时一下
			// #endif

			// H5端
			// #ifdef H5
			window.addEventListener('message', e => {
				this.webV = e.source // window的对象
				// 接收Html发送过来的消息, 控制台打印看结果
				console.log(e.data.data.arg, '接收h5页面发来的消息');
			}, false)
			// #endif
		},
		methods: {
			// 手机上运行时点击 postMessage 会走这里
			message(e) {
				console.log('app上测试接收 webview 传过来的值', e.detail.data)
			},
			//uniapp 向 web 端传值
			submit() {
				let obj = {
					name: 'wft'
				}
				// 这里解释下 evalJS 是什么东西
				// evalJS是一种 JavaScript 注入技术,其原理是在运行时将动态生成的 JavaScript 代码注入到网页中,并且立即执行该代码。
				// JavaScript 注入通常用于扩展或修改网页上的功能。它可以通过将自定义的 JavaScript 代码插入到网页的上下文中,来实现对网页的修改或操控。
				// 注入的 JavaScript 代码可以访问和修改网页的 DOM 元素、调用网页提供的 API,以及与页面上的其他 JavaScript 代码进行交互。
				
				//传递的参数如果是引用类型,就要 JSON.stringify 转一下,否则报错
				// `msgFromUniapp(${JSON.stringify(obj)})` 这里其实相当于在 web 端调用了此方法
				wv.evalJS(`msgFromUniapp(${JSON.stringify(obj)})`);
			}
		}
	}
</script>

<style lang="scss" scoped>
</style>

web端

1.创建一个本地文件夹,并创建html等相关文件,具体如下

2.创建 uniwebview.js 文件,这个文件其实是 uniapp 的官方包,在我使用这个线上包的时候发生了报错,这里建议大家创建个本地文件,并在这个 html 引用这个文件

注意:下面的代码是当前 uniapp 中的webview.js 官方包体,版本是 1.1.5

!(function (e, n) {
  'object' == typeof exports && 'undefined' != typeof module
    ? (module.exports = n())
    : 'function' == typeof define && define.amd
    ? define(n)
    : ((e = e || self).uni = n());
})(this, function () {
  'use strict';
  try {
    var e = {};
    Object.defineProperty(e, 'passive', {
      get: function () {
        !0;
      },
    }),
      window.addEventListener('test-passive', null, e);
  } catch (e) {}
  var n = Object.prototype.hasOwnProperty;

  function i(e, i) {
    return n.call(e, i);
  }
  var t = [];

  function r() {
    return window.__dcloud_weex_postMessage || window.__dcloud_weex_;
  }
  var o = function (e, n) {
      var i = {
        options: {
          timestamp: +new Date(),
        },
        name: e,
        arg: n,
      };
      if (r()) {
        if ('postMessage' === e) {
          var o = {
            data: [n],
          };
          return window.__dcloud_weex_postMessage
            ? window.__dcloud_weex_postMessage(o)
            : window.__dcloud_weex_.postMessage(JSON.stringify(o));
        }
        var a = {
          type: 'WEB_INVOKE_APPSERVICE',
          args: {
            data: i,
            webviewIds: t,
          },
        };
        window.__dcloud_weex_postMessage
          ? window.__dcloud_weex_postMessageToService(a)
          : window.__dcloud_weex_.postMessageToService(JSON.stringify(a));
      }
      if (!window.plus)
        return window.parent.postMessage(
          {
            type: 'WEB_INVOKE_APPSERVICE',
            data: i,
            pageId: '',
          },
          '*'
        );
      if (0 === t.length) {
        var d = plus.webview.currentWebview();
        if (!d) throw new Error('plus.webview.currentWebview() is undefined');
        var s = d.parent(),
          w = '';
        (w = s ? s.id : d.id), t.push(w);
      }
      if (plus.webview.getWebviewById('__uniapp__service'))
        plus.webview.postMessageToUniNView(
          {
            type: 'WEB_INVOKE_APPSERVICE',
            args: {
              data: i,
              webviewIds: t,
            },
          },
          '__uniapp__service'
        );
      else {
        var u = JSON.stringify(i);
        plus.webview
          .getLaunchWebview()
          .evalJS(
            'UniPlusBridge.subscribeHandler("'
              .concat('WEB_INVOKE_APPSERVICE', '",')
              .concat(u, ',')
              .concat(JSON.stringify(t), ');')
          );
      }
    },
    a = {
      navigateTo: function () {
        var e =
            arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
          n = e.url;
        o('navigateTo', {
          url: encodeURI(n),
        });
      },
      navigateBack: function () {
        var e =
            arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
          n = e.delta;
        o('navigateBack', {
          delta: parseInt(n) || 1,
        });
      },
      switchTab: function () {
        var e =
            arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
          n = e.url;
        o('switchTab', {
          url: encodeURI(n),
        });
      },
      reLaunch: function () {
        var e =
            arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
          n = e.url;
        o('reLaunch', {
          url: encodeURI(n),
        });
      },
      redirectTo: function () {
        var e =
            arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {},
          n = e.url;
        o('redirectTo', {
          url: encodeURI(n),
        });
      },
      getEnv: function (e) {
        r()
          ? e({
              nvue: !0,
            })
          : window.plus
          ? e({
              plus: !0,
            })
          : e({
              h5: !0,
            });
      },
      postMessage: function () {
        var e =
          arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
        o('postMessage', e.data || {});
      },
    },
    d = /uni-app/i.test(navigator.userAgent),
    s = /Html5Plus/i.test(navigator.userAgent),
    w = /complete|loaded|interactive/;
  var u =
    window.my &&
    navigator.userAgent.indexOf(
      ['t', 'n', 'e', 'i', 'l', 'C', 'y', 'a', 'p', 'i', 'l', 'A']
        .reverse()
        .join('')
    ) > -1;
  var g =
    window.swan && window.swan.webView && /swan/i.test(navigator.userAgent);
  var v =
    window.qq &&
    window.qq.miniProgram &&
    /QQ/i.test(navigator.userAgent) &&
    /miniProgram/i.test(navigator.userAgent);
  var c =
    window.tt &&
    window.tt.miniProgram &&
    /toutiaomicroapp/i.test(navigator.userAgent);
  var m =
    window.wx &&
    window.wx.miniProgram &&
    /micromessenger/i.test(navigator.userAgent) &&
    /miniProgram/i.test(navigator.userAgent);
  var p = window.qa && /quickapp/i.test(navigator.userAgent);
  var f =
    window.ks &&
    window.ks.miniProgram &&
    /micromessenger/i.test(navigator.userAgent) &&
    /miniProgram/i.test(navigator.userAgent);
  var l =
    window.tt &&
    window.tt.miniProgram &&
    /Lark|Feishu/i.test(navigator.userAgent);
  var _ =
    window.jd &&
    window.jd.miniProgram &&
    /micromessenger/i.test(navigator.userAgent) &&
    /miniProgram/i.test(navigator.userAgent);
  var E =
    window.xhs &&
    window.xhs.miniProgram &&
    /xhsminiapp/i.test(navigator.userAgent);
  for (
    var h,
      P = function () {
        (window.UniAppJSBridge = !0),
          document.dispatchEvent(
            new CustomEvent('UniAppJSBridgeReady', {
              bubbles: !0,
              cancelable: !0,
            })
          );
      },
      b = [
        function (e) {
          if (d || s)
            return (
              window.__dcloud_weex_postMessage || window.__dcloud_weex_
                ? document.addEventListener('DOMContentLoaded', e)
                : window.plus && w.test(document.readyState)
                ? setTimeout(e, 0)
                : document.addEventListener('plusready', e),
              a
            );
        },
        function (e) {
          if (m)
            return (
              window.WeixinJSBridge && window.WeixinJSBridge.invoke
                ? setTimeout(e, 0)
                : document.addEventListener('WeixinJSBridgeReady', e),
              window.wx.miniProgram
            );
        },
        function (e) {
          if (v)
            return (
              window.QQJSBridge && window.QQJSBridge.invoke
                ? setTimeout(e, 0)
                : document.addEventListener('QQJSBridgeReady', e),
              window.qq.miniProgram
            );
        },
        function (e) {
          if (u) {
            document.addEventListener('DOMContentLoaded', e);
            var n = window.my;
            return {
              navigateTo: n.navigateTo,
              navigateBack: n.navigateBack,
              switchTab: n.switchTab,
              reLaunch: n.reLaunch,
              redirectTo: n.redirectTo,
              postMessage: n.postMessage,
              getEnv: n.getEnv,
            };
          }
        },
        function (e) {
          if (g)
            return (
              document.addEventListener('DOMContentLoaded', e),
              window.swan.webView
            );
        },
        function (e) {
          if (c)
            return (
              document.addEventListener('DOMContentLoaded', e),
              window.tt.miniProgram
            );
        },
        function (e) {
          if (p) {
            window.QaJSBridge && window.QaJSBridge.invoke
              ? setTimeout(e, 0)
              : document.addEventListener('QaJSBridgeReady', e);
            var n = window.qa;
            return {
              navigateTo: n.navigateTo,
              navigateBack: n.navigateBack,
              switchTab: n.switchTab,
              reLaunch: n.reLaunch,
              redirectTo: n.redirectTo,
              postMessage: n.postMessage,
              getEnv: n.getEnv,
            };
          }
        },
        function (e) {
          if (f)
            return (
              window.WeixinJSBridge && window.WeixinJSBridge.invoke
                ? setTimeout(e, 0)
                : document.addEventListener('WeixinJSBridgeReady', e),
              window.ks.miniProgram
            );
        },
        function (e) {
          if (l)
            return (
              document.addEventListener('DOMContentLoaded', e),
              window.tt.miniProgram
            );
        },
        function (e) {
          if (_)
            return (
              window.JDJSBridgeReady && window.JDJSBridgeReady.invoke
                ? setTimeout(e, 0)
                : document.addEventListener('JDJSBridgeReady', e),
              window.jd.miniProgram
            );
        },
        function (e) {
          if (E) return window.xhs.miniProgram;
        },
        function (e) {
          return document.addEventListener('DOMContentLoaded', e), a;
        },
      ],
      y = 0;
    y < b.length && !(h = b[y](P));
    y++
  );
  h || (h = {});
  var B = 'undefined' != typeof uni ? uni : {};
  if (!B.navigateTo) for (var S in h) i(h, S) && (B[S] = h[S]);
  return (B.webView = h), B;
});

3.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">
      .desc {
        color: #999999;
      }
      * {
        margin: 0;
        padding: 0;
      }
      .btn {
        display: block;
        margin: 20px auto;
        padding: 5px;
        background-color: #007aff;
        border: 0;
        color: #ffffff;
        height: 40px;
        width: 200px;
      }

      .btn-red {
        background-color: #dd524d;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <p class="desc">
        网页向应用发送消息,注意:小程序端应用会在此页面后退时接收到消息。
      </p>
      <div class="btn-list">
        <button class="btn btn-red" type="button" id="postMessage">
          postMessage
        </button>
        <input type="file" accept="image/*" multiple onchange="uploadImg()" />
      </div>
    </div>
    <!-- 引用的是从uniapp官网上下载的 webview.js ,当前是 1.1.5 版本 -->
    <script type="text/javascript" src="./uniwebview.js"></script>
    <script type="text/javascript">
      // 上传文件转 base64
      var files = null;
      function uploadImg(event) {
        var e = window.event || event;
        let Files = e.target.files[0];
        var reader = new FileReader();
        reader.readAsDataURL(Files); // 解析成base64格式
        reader.onload = function () {
          files = this.result;
        };
      }

      // 待触发 `UniAppJSBridgeReady` 事件后,即可调用 uni 的 API。
      document.addEventListener('UniAppJSBridgeReady', () => {
        document
          .getElementById('postMessage')
          .addEventListener('click', function () {
            // 向uniapp传值
            console.log(files);
            uni.postMessage({
              data: {
                name: '流云借风真君',
                age: '5000',
                //这里尝试 web 端向 uniapp 传 blob 和 base64
                //发现 app 端接收不到 blob,但是可以接收 base64
                // H5 端可以接收 blob,也可以接收 base64
                img: files,
              },
            });
          });
      });

      // uniapp传过来的值
      window.msgFromUniapp = function (arg) {
        //传过来的值如果是复杂数据类型,需要 JSON.stringify 才能拿到
        console.log('uniapp传过来的值', JSON.stringify(arg));
      };
    </script>
  </body>
</html>

4.用 live server 运行这个 html 文件,再去 app 中和 H5 中测试通信

5.运行之后浏览器中应该是这样,此时这个地址是 live server 创建的一个服务,在H5 端能在 webview 中可以访问这个地址,但是app不行,因为 live server 创建的服务,app上并不能访问,但是只要你运行 app 用的是当前ip地址的电脑就可以用 app 访问这个 ip 地址,所以 uniapp 中的 webview 要引用当前运行项目的电脑的 ip 地址.

6.正确的地址应该是这样,记得加端口号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微光无限

破晓的日子还有很多!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值