【案例】uniapp实现内部信息与外部的html网页双向通信的完整的过程,附加完整的代码部分

uniapp实现内部容易与外部的html实现双向通信

以下提供完整的实现uniapp内部的容器获取到坐标,实现外部的网页html发起获取坐标的信号,然后uniapp获取到本机的坐标后,将获取到的坐标传递给外部的html上并且弹窗显示的整个过程,代码百分百正确,且能够实现双向传递信息!!!

1.内部vue的代码截图:


2.HBuilderX内的vue的代码如下:

bash 复制代码
<template>
  <view class="container">
    <web-view 
      id="remoteH5"
      :src="h5Url" 
      @message="handleH5Message"
    ></web-view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      h5Url: 'http://192.168.0.242/Location.html',
      subWebview: null
    };
  },

  mounted() {
    // #ifdef APP-PLUS
    this.waitForSubWebview();
    // #endif
  },

  methods: {
    // 🔁 轮询获取子 webview(直到成功或超时)
    waitForSubWebview(maxRetry = 20, interval = 100) {
      let attempts = 0;
      const check = () => {
        if (this.subWebview) return; // 已获取,退出

        const pages = getCurrentPages();
        const page = pages[pages.length - 1];
        const currentWebview = page.$getAppWebview();
        const children = currentWebview.children();

        if (children && children.length > 0) {
          this.subWebview = children[0];
          console.log('[UniApp] ✅ 成功获取子 webview:', this.subWebview.getURL());
          // 可选:监听子页 loaded(更保险)
          this.subWebview.onloaded = () => {
            console.log('[UniApp] 🟢 子页面 DOM 已加载完成');
          };
        } else if (attempts < maxRetry) {
          attempts++;
          setTimeout(check, interval);
        } else {
          console.error('[UniApp] ❌ 超时:未能获取子 webview');
        }
      };

      check(); // 立即首次检查
    },

    handleH5Message(e) {
      const msg = e.detail.data?.[0];
      if (!msg || !msg.action) return;

      console.log('[UniApp] 📥 收到 HTML 消息:', msg);

      if (msg.action === 'requestLocation') {
        this.getLocationAndSendToH5();
      }
    },

    getLocationAndSendToH5() {
      uni.showLoading({ title: '定位中...' });

      uni.getLocation({
        type: 'gcj02',
        success: (res) => {
          uni.hideLoading();
          const { latitude, longitude } = res;

          // ✅ 关键:用子 webview evalJS,调用 HTML 的 receiveFromUniApp
          // #ifdef APP-PLUS
          if (this.subWebview) {
            const data = {
              action: 'locationResult',
              latitude: latitude,
              longitude: longitude,
              accuracy: res.accuracy
            };
            const script = `typeof receiveFromUniApp === 'function' ? receiveFromUniApp(${JSON.stringify(data)}) : console.error('[H5] receiveFromUniApp 未定义!')`;
            this.subWebview.evalJS(script);
            console.log('[UniApp] ✅ 坐标已注入 HTML');
          } else {
            // 若仍无子页,走 fallback:延迟重试
            setTimeout(() => {
              if (this.subWebview) {
                this.getLocationAndSendToH5(); // 重试一次
              } else {
                uni.showToast({ title: '页面未就绪,请稍后重试', icon: 'none', duration: 2000 });
              }
            }, 500);
          }
          // #endif
        },
        fail: (err) => {
          uni.hideLoading();
          // #ifdef APP-PLUS
          if (this.subWebview) {
            this.subWebview.evalJS(`receiveFromUniApp({ action: 'locationError', message: ${JSON.stringify(err.errMsg)} })`);
          }
          // #endif
        }
      });
    }
  }
};
</script>

<style>
.container { width: 100%; height: 100vh; }
</style>

3.外部的html中的代码的部分截图:


uni.webview.1.5.5.js内的代码(自己创建,负责进去百分百可以用):

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

4.外部的html中的代码截图:

bash 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>UniApp 通信测试 - 初始化参数支持</title>
  <style>
    body { 
      padding: 20px; 
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; 
      line-height: 1.6;
    }
    .btn {
      padding: 10px 20px;
      background: #007aff;
      color: white;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      margin: 8px 0;
      font-size: 16px;
    }
    #log {
      margin-top: 20px;
      padding: 15px;
      background: #f9f9f9;
      border: 1px solid #eee;
      border-radius: 6px;
      white-space: pre-wrap;
      font-family: 'Courier New', monospace;
      max-height: 400px;
      overflow-y: auto;
      font-size: 14px;
    }
    .highlight { background-color: #e6f7ff; }
  </style>
</head>
<body>
  <h3>📍 UniApp 双向通信测试(含初始化参数)</h3>
  <p>✅ 页面加载时将自动接收 UniApp 传入的参数并弹窗</p>
  <button class="btn" onclick="requestLocation()">🔄 获取 UniApp 定位</button>
  <div id="log">日志输出:</div>
</body>
  <!-- ⚠️ 关键:receiveFromUniApp 必须在 SDK 加载前定义! -->
  <script>
    // 💡 【第一优先级】暴露全局接收函数(必须早于 uni.webview.js!)
    window.receiveFromUniApp = function(data) {
      const logEl = document.getElementById('log');
      const now = new Date().toLocaleTimeString();
      
      // 日志记录
      const line = `[${now}] 📥 收到 UniApp 消息: ${JSON.stringify(data, null, 2)}`;
      logEl.innerHTML += '\n' + line;
      logEl.scrollTop = logEl.scrollHeight;
      console.log('[H5] receiveFromUniApp called with:', data);
      console.log('[H5] receiveFromUniApp called with 转为json:', `${JSON.stringify(data, null, 2)}`);

      // 🔑 【核心】处理初始化参数
      if (data.action === 'initParams') {
        const payload = data.payload;
        console.log('✅✅✅ 成功获取 UniApp 初始化参数:', payload);
        
        // 👇 弹窗显示(按你需求)
        const msg = `【UniApp 初始化参数】\n` +
                    `👤 用户ID:${payload.userId}\n` +
                    `🔑 Token:${payload.token}\n` +
                    `🌐 环境:${payload.env}\n` +
                    `⏱ 时间戳:${payload.timestamp}`;
        
        alert(msg); // 或改用更美观的 modal

        // 📤 回传确认(触发 UniApp 的 echoReceivedData 逻辑)
        if (window.uni && typeof uni.postMessage === 'function') {
          uni.postMessage({
            data: {
              action: 'echoReceivedData',
              payload: data
            }
          });
          console.log('[H5] 📤 已回传 initParams 确认');
        }
        return;
      }

      // 处理定位结果
      if (data.action === 'locationResult') {
        const { latitude, longitude, accuracy } = data;
        const msg = `\n🟢 定位成功!\n纬度: ${latitude}\n经度: ${longitude}\n精度: ${accuracy}米`;
        logEl.innerHTML += msg;
        alert(`✅ 定位成功!\n纬度:${latitude}\n经度:${longitude}`);
        return;
      }

      // 处理定位失败
      if (data.action === 'locationError') {
        logEl.innerHTML += `\n🔴 定位失败:${data.message}`;
        alert('❌ 定位失败:' + data.message);
        return;
      }

      // 兜底处理
      console.warn('[H5] 未知消息类型:', data.action);
    };
  </script>

  <!-- ✅ 加载 Uni Webview SDK(建议本地化!) -->
  <script src="./uni.webview.1.5.5.js"></script>
  <!-- 若坚持用 CDN(局域网需确保能访问) -->
  <!-- <script src="https://js.cdn.aliyun.com/uniapp/1.5.5/uni.webview.1.5.5.js  "></script> -->

  <script>
    // 【增强】监听桥接就绪,并主动通知 UniApp
    document.addEventListener('UniAppJSBridgeReady', function() {
      log('[H5] 🟢 UniAppJSBridgeReady 触发 --- 桥已就绪');
      // 等待 100ms 确保 receiveFromUniApp 已定义(虽已前置,仍保守)
      setTimeout(() => {
        if (typeof uni !== 'undefined' && uni.postMessage) {
          uni.postMessage({
            data: { action: 'h5Ready' }
          });
          log('[H5] 📤 已通知 UniApp:H5 页面就绪,等待初始化参数...');
        } else {
          log('[H5] ❗uni 未定义,postMessage 不可用');
        }
      }, 100);
    });

    // 【兜底】监听 window.postMessage(某些 Android 基座会走此通道)
    window.addEventListener('message', function(e) {
      if (e.data && e.data.action && typeof window.receiveFromUniApp === 'function') {
        log('[H5] 📥 通过 window.postMessage 收到消息(兜底通道)');
        receiveFromUniApp(e.data);
      }
    });

    // 按钮功能
    function requestLocation() {
      if (!window.uni) return alert('❌ 请在 UniApp App 中打开本页面!(当前无 uni 对象)');
      uni.postMessage({
        data: { action: 'requestLocation' }
      });
      log('[H5] 📤 已请求定位');
    }


    // 通用日志函数
    function log(msg) {
      const el = document.getElementById('log');
      el.innerHTML += '\n' + msg;
      el.scrollTop = el.scrollHeight;
    }

    // 页面 load 兜底检查
    window.addEventListener('load', () => {
      log('[H5] 🟡 页面 load 完成');
      if (typeof receiveFromUniApp !== 'function') {
        log('[H5] ❗严重错误:receiveFromUniApp 未定义!请检查 JS 加载顺序');
      }
    });
  </script>

</html>

结果展示:

实现双向通信,内部与外部进行数据通信,传递参数:

相关推荐
郑州光合科技余经理1 小时前
开发指南:海外版外卖跑腿系统源码解析与定制
java·开发语言·mysql·spring cloud·uni-app·php·深度优先
2501_916008891 小时前
提高 iOS 应用逆向难度的工程实践,多工具联动的全栈安全方案
android·安全·ios·小程序·uni-app·cocoa·iphone
爱泡脚的鸡腿1 小时前
uni-app D4 实战(小兔鲜)
前端·vue.js·架构
星火飞码iFlyCode1 小时前
iFlyCode+SpecKit应用:照片等比智能压缩功能实现
前端·javascript
广白1 小时前
钉钉小程序直传文件到 阿里云OSS
前端·vue.js·uni-app
zyfts2 小时前
🔥告别 20 分钟等待!NestJS 生产级消息队列 BullMQ 实践指南
前端·后端
狗头大军之江苏分军2 小时前
【压力】一位一线炼钢工人的消失
前端·后端
拉不动的猪3 小时前
文件下载:后端配置、前端方式与进度监控
前端·javascript·浏览器
Amy_yang3 小时前
前端实现 Server-Sent Events 全解析:从代码到调试的实战指南
前端·uni-app