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

发布时间:2024年01月10日

先去官网了解下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.正确的地址应该是这样,记得加端口号

文章来源:https://blog.csdn.net/sdhshsjh/article/details/135508544
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。