玩转 UniApp WebView:H5 与原生应用双向通信实战

玩转 UniApp WebView:H5 与原生应用双向通信实战

在 UniApp 开发中,WebView 是连接原生应用与 H5 页面的重要桥梁,尤其在需要复用已有 Web 页面或集成复杂 Web 交互场景时不可或缺。本文将结合实际开发案例,详细讲解如何实现 UniApp(App/H5 端)与内嵌 H5 页面的双向通信,并封装常用的原生能力调用(扫码、拨打电话、蓝牙打印、文件上传等)。

一、核心需求与技术背景

你需要在 UniApp 中通过 WebView 嵌入 H5 页面,并实现:

  1. H5 页面触发原生能力(扫码、拨打电话、蓝牙打印、图片 / 视频上传);
  2. UniApp 原生端处理完逻辑后,将结果回传给 H5 页面;
  3. 兼容 App 端和 H5 端的通信逻辑;
  4. 给 H5 页面传递鉴权 Token 等参数。

二、整体实现思路

  1. 参数传递:UniApp 在打开 WebView 时,通过 URL 拼接方式给 H5 页面传递 Token 等参数;
  2. H5 → UniApp:H5 通过uni.webView.postMessage发送指令,UniApp 监听message事件接收并处理;
  3. UniApp → H5:UniApp 通过evalJS执行 H5 页面的全局函数,将处理结果回传;
  4. 端兼容:通过 UniApp 的条件编译区分 App 端和 H5 端的通信逻辑。

三、代码实现详解

3.1 UniApp 端:WebView 容器页面

<template><view style="position: relative;"><web-view :src="reportSrc":webview-styles="webviewStyles" @message="message"></web-view></view></template><script>import{ getToken }from'@/utils/auth'import cameraTool from'../mixins/camera-tool.vue'// 上传功能混入var wv;// WebView实例exportdefault{mixins:[cameraTool],data(){return{webviewStyles:{width:'100%',height:'100%'},reportSrc:''};},onLoad(option){// 接收打开页面时传递的参数const eventChannel =this.getOpenerEventChannel(); eventChannel.on('acceptDataFromOpenerPage',(data)=>{this.reportSrc =this.addQueryParam(data.url,`token=${getToken()}`); uni.setNavigationBarTitle({title: data.title });});// #ifdef APP-PLUSthis.initAppWebView();// #endif// #ifdef H5this.initH5Listener();// #endif},methods:{// App端WebView初始化initAppWebView(){ uni.showLoading({title:'加载中'});var currentWebview =this.$scope.$getAppWebview();setTimeout(()=>{ wv = currentWebview.children()[0]; uni.hideLoading();},1000);},// H5端监听initH5Listener(){ window.addEventListener('message',(e)=>{ console.log('接收H5消息', e.data);},false);},// URL拼接TokenaddQueryParam(url, param){return url.includes('?')?`${url}&${param}`:`${url}?${param}`;},// 接收H5发来的消息(核心)message(e){const data = e.detail.data[0];const{ type, info, options }= data;const actions ={'scanCode':()=>this.handleScan(info),'phoneCall':()=>this.handlePhoneCall(info),'bluetoothPrint':()=>this.handleBluetoothPrint(info),'chooseImage':()=>this.handleChooseImage(options),'chooseVideo':()=>this.handleChooseVideo(options),'logout':()=>this.handleLogout()};if(actions[type]){ actions[type]();}else{ console.warn('未知操作类型:', type);}},// 扫一扫handleScan(){ uni.scanCode({success:(res)=>{ wv.evalJS(`window.scanCodeFromUniApp('${res.result}')`);}});},// 拨打电话handlePhoneCall(phoneNumber){ uni.makePhoneCall({phoneNumber: phoneNumber ||'114'});},// 蓝牙打印(跳转蓝牙页面)handleBluetoothPrint(printData){ uni.navigateTo({url:`/pages/common/blueTooth/index?printData=${JSON.stringify(printData)}`});},// 上传图片asynchandleChooseImage(options){try{const imageUrl =awaitthis.uploadImage(options); wv.evalJS(`window.chooseImageFromUniApp(${JSON.stringify(imageUrl)})`);}catch(error){ console.error('图片上传失败', error);}},// 上传视频asynchandleChooseVideo(options){try{const videoUrl =awaitthis.uploadVideo(options); wv.evalJS(`window.chooseVideoFromUniApp(${JSON.stringify(videoUrl)})`);}catch(error){ console.error('视频上传失败', error);}},// App主动向H5传值submit(){const data ={name:'wft',timestamp: Date.now()}; wv.evalJS(`window.msgFromUniApp(${JSON.stringify(data)})`);}}};</script>

3.2 H5 端:页面结构与通信逻辑

3.2.1 HTML 入口文件(index.html)
<!DOCTYPE html><html><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/></head><body><div id="app"></div><!-- 关键:引入 uni.webView 桥接文件 --><script src="./uni.webview.js" type="text/javascript"></script><script type="text/javascript">// 等待桥接就绪 document.addEventListener("UniAppJSBridgeReady",function(){ uni.webView.getEnv(function(res){ console.log("当前环境:", res);});});// 声明供 App 调用的全局函数 window.msgFromUniApp=function(val){}; window.scanCodeFromUniApp=function(val){}; window.chooseImageFromUniApp=function(val){}; window.chooseVideoFromUniApp=function(val){};</script></body></html>
3.2.2 H5 业务页面(A.vue)
<template><div class="hello"><h3>H5内嵌页面</h3><!-- 扫一扫 --><van-field v-model="scanCode" label="扫一扫" placeholder="扫码结果"><template #button><van-button type="primary" size="small" @click="handleScan"> 扫一扫 </van-button></template></van-field><!-- 拨打电话 --><van-field v-model="phone" label="拨打电话"><template #button><van-button type="primary" size="small" @click="makePhoneCall"> 拨打 </van-button></template></van-field><!-- 蓝牙打印 --><div class="section"><van-button type="primary" size="small" @click="handleBluetoothPrint"> 蓝牙打印 </van-button></div><!-- 上传图片 --><div class="section"><div class="preview"><img v-for="item in fileList":key="item.url":src="item.url"/></div><van-button type="primary" size="small" @click="handleUploadImage"> 上传图片 </van-button></div><!-- 上传视频 --><div class="section"><div class="preview"><video v-for="item in videoList":key="item.url":src="item.url" controls /></div><van-button type="primary" size="small" @click="handleUploadVideo"> 上传视频 </van-button></div></div></template><script>exportdefault{data(){return{scanCode:'',phone:'13800138000',fileList:[],videoList:[]};},mounted(){// 重写全局回调,接收App执行结果 window.scanCodeFromUniApp=(val)=>{this.scanCode = val;}; window.chooseImageFromUniApp=(val)=>{this.fileList =this.fileList.concat(val);}; window.chooseVideoFromUniApp=(val)=>{this.videoList =this.videoList.concat(val);}; window.msgFromUniApp=(val)=>{ console.log('App主动消息:', val);};},methods:{// 统一消息发送入口postMessage(type, payload ={}){if(!window.uni ||!window.uni.webView){ console.error('uni.webView 未就绪');return;} window.uni.webView.postMessage({data:{ type,...payload }});},handleScan(){this.postMessage('scanCode');},makePhoneCall(){this.postMessage('phoneCall',{info:this.phone });},handleBluetoothPrint(){this.postMessage('bluetoothPrint',{info:[11,22]});},handleUploadImage(){this.postMessage('chooseImage',{options:{maxNumber:2,sourceTypeIndex:3,// 1:相机 2:相册 3:两者sizeTypeIndex:2,// 1:压缩 2:原图 3:两者url:'http://your-server/upload',bucketName:'jingsheng'}});},handleUploadVideo(){this.postMessage('chooseVideo',{options:{maxDuration:60,sourceTypeIndex:3,url:'http://your-server/upload',bucketName:'jingsheng'}});}}};</script>

四、关键注意事项

  • 本地 H5 调试:本地运行的 H5 页面需用Live Server打开,且地址需替换成本机
    IP(如192.168.1.4:5500),而非127.0.0.1,否则手机端无法访问;
  • App 端 webview 实例:必须通过this. s c o p e . scope. scope.getAppWebview()获取,且需延时 1
    秒左右确保实例创建完成;
  • 参数传递格式:通过evalJS传递复杂数据时,需用JSON.stringify序列化,避免语法错误;
  • 端兼容处理:通过#ifdef APP-PLUS/#ifdef H5区分不同端的通信逻辑,H5
    端需用window.postMessage,App 端用evalJS;
  • 权限申请:调用扫码、拨打电话、文件上传等功能时,需在manifest.json中配置对应权限。
  • App 端使用 uni.web-view.js 的最低版为 uni.webview.1.5.4.js

五、总结

  • UniApp 与 H5 的双向通信核心是:H5 通过uni.webView.postMessage发消息,UniApp 通过evalJS执行 H5 全局函数回传结果;
  • 需通过条件编译区分 App 端和 H5 端的通信逻辑,App 端依赖 webview 实例,H5 端依赖 window 对象;
  • 实际开发中需注意本地调试的 IP 替换、参数序列化、权限配置等细节,确保跨端通信稳定可靠。

通过这套方案,你可以轻松实现 UniApp 原生能力与 H5 页面的深度融合,既复用了 Web 端的开发成果,又能充分利用原生应用的功能优势。

Read more

AMR机器人:如何满足现代物料搬运的需求

AMR机器人:如何满足现代物料搬运的需求

在瞬息万变的生产装配环境中,每一秒都至关重要。原材料、零部件和成品的流动必须保持顺畅,以避免瓶颈和停机。传统上,企业依靠叉车、牵引车和手动推车将物料从生产车间的一个区域运送到另一个区域。 在繁忙的生产区域,有人驾驶的叉车可能带来严重的安全隐患,而手动搬运车和牵引车则耗时费力且效率低下。在当今快速发展的制造业中,灵活性和效率至关重要,这些传统方法已无法满足生产需求。  自主移动机器人 (AMR) 是重塑该领域最具变革性的技术之一。这些智能机器正在革新仓库运营,带来前所未有的效率、灵活性和成本效益。 作为AMR 与无人叉车解决方案提供商,AiTEN 海豚之星正通过自动移动机器人(AMR)技术,帮助企业构建更加高效、柔性、安全和可持续的现代物料搬运体系。 什么是 AMR? AMR(Autonomous Mobile Robot)是一种能够在复杂环境中自主感知、自主决策、自主执行任务的智能移动设备。与传统的AGV(自动导引车)相比,AMR无需对工作环境进行大规模改造,具有更高的灵活性和适应性。 AiTEN Robotics 的 AMR 解决方案基于全栈自研技术架构,具备以下核

万字长文:重点区域低空安全防御系统(反无人机)深度实战方案 | 从0到1构建立体安防体系(WORD)

万字长文:重点区域低空安全防御系统(反无人机)深度实战方案 | 从0到1构建立体安防体系(WORD)

摘要:随着低空经济爆发式增长,无人机"黑飞"已成为国家重点区域安防的重大威胁。本文基于真实政务项目案例,深度解析一套覆盖"探测-识别-定位-反制-溯源"全链条的低空安全防御系统建设方案。全文8000+字,涵盖TDOA无源定位、相控阵雷达、导航诱骗等核心技术,以及等保2.0合规、电磁频谱安全等实施细节,为安防系统集成商、智慧城市建设者提供保姆级技术参考。 一、项目背景与战略价值:低空经济背后的安全缺口 1.1 低空经济崛起的"双刃剑"效应 近年来,随着《"十四五"数字经济发展规划》的深入推进,低空经济已被纳入国家战略性新兴产业序列。无人机在物流配送、电力巡检、应急救援、城市测绘等领域的应用呈现爆发式增长。据统计,截至2025年初,我国民用无人机保有量已突破500万架,年飞行时长超过数千万小时。 然而,

荣耀“机器人”上演实战“变形记”,手机进化为“AI新形态”!

荣耀“机器人”上演实战“变形记”,手机进化为“AI新形态”!

在2026年巴塞罗那世界移动通信大会(MWC 2026)上,荣耀给出了一个极具冲击力的答案:它不再仅仅是一部智能手机,而是向着“AI硬件生态系统”进化,推出了具身智能新形态的Robot Phone以及其首款消费级人形机器人ROBOT。 1. Robot Phone:不只是翻转摄像头那么简单 荣耀在发布会现场展示了名为Robot Phone的概念机,这款手机的最大亮点是顶部配备了一个安装在机械臂上的2亿像素摄像头。不同于传统的翻盖摄像头,它不仅可以机械地翻转,而且在荣耀AI大模型的加持下,手机摄像头能够感知环境并做出反应。 正如荣耀方面所描述的,“Robot Phone不再是一个冷冰冰的设备,而是兼具智能度和生命感的人类伙伴,是一个不断进化的新物种”。它可以在用户拍照时自动追踪主体、识别语音指令甚至进行手势识别,仿佛手机本身拥有了“眼睛”和“手脚”。这不仅是硬件的创新,更是软件层面的变革,荣耀试图通过这款手机将用户带入一个人与设备无缝交互的未来场景。 2. 首款人形机器人ROBOT:从“手机”到“伙伴” 与Robot Phone形成呼应的,是荣耀在本次MWC上同步亮相的首款

OpenClaw(Clawdbot)插件更新,新增支持在面板一键QQ和飞书机器人

OpenClaw(Clawdbot)插件更新,新增支持在面板一键QQ和飞书机器人

这次,OpenClaw 插件迎来了一次重要更新。 现在,你可以直接在插件中配置 飞书机器人或 QQ 机器人,让 OpenClaw 真正走出 Web 界面,进入你日常使用的消息工具中。 无需额外部署服务,配置完成后即可开始对话。 重要提示:由于官方更改包名,不支持直接升级,如需更新请卸载旧版插件,安装新版OpenClaw插件,已有数据会丢失,请您评估是否需要更新,新安装不受影响。 配置QQ机器人1. 打开QQ开放平台,注册账号,如已注册可直接登陆 点击编辑 IP 白名单,填写服务器 IP 并保存 点击开发管理,获取APPID、AppSecret 创建完成后点击刚刚创建的机器人 填写机器人基础信息 登录后点击机器人,创建机器人 按提示完成登录 8.将获取到的信息填写到插件,并保存启用 添加后即可在群聊中进行对话 在此处添加完成后回到QQ-群管理-添加机器人,在其他页面找到机器人 选择需要使用的群聊 回到QQ机器人平台,