所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

uni-app Webview通信实现全攻略:详细方法+实战示例一看就会

uni-app Webview通信实现全攻略:详细方法+实战示例一看就会 一

文章目录CloseOpen

我们把uni-app Webview通信的底层逻辑、实现步骤拆成了能直接落地的操作指南——从Webview组件的基础配置、原生与H5的双向消息传递,到复杂参数的序列化解析、常见兼容性问题规避,每一步都配了可复制运行的实战示例。不管你是刚入门的新手,还是想优化通信逻辑的老开发,不用猜坑踩雷,跟着示例走,5分钟搞定消息发送,10分钟掌握参数互传,连“跨域拦截”“消息丢失”这些棘手问题都帮你提前解决了!

读完这篇,Webview通信再也不是你的开发障碍——方法讲透了,示例给全了,直接上手就能用,真正做到“一看就会”!

你有没有过这种情况?在uni-app里用Webview加载H5页面,想传个商品ID过去,结果H5页面收不到;或者H5想把用户操作反馈给原生页面,原生那边跟没听见似的——去年帮朋友做电商小程序时,我就碰到过这种糟心事儿:他用Webview加载商品详情页,一开始传商品ID总丢参数,用户点进去看到的全是默认内容,差点把客户搞丢。后来我帮他把通信逻辑拆了一遍,才发现问题出在“没搞懂Webview和原生的边界”“消息格式没处理对”这两个关键点上。今天这篇攻略,就是把我踩过的坑、试有效的方法,全拆成能直接抄的步骤——不管你是第一次碰Webview,还是之前踩过坑,跟着做就能搞定双向通信。

为什么uni-app Webview通信总踩坑?先搞懂底层逻辑

要解决通信问题,得先明白uni-app的Webview到底是啥——它本质是嵌套在原生页面里的H5容器,相当于在你的小程序或App里开了个“小浏览器”,加载的H5页面和原生页面是两个完全隔离的环境:原生页面用的是uni-app的Vue框架,H5页面用的是浏览器的JS环境,两者的数据、变量都不互通。就像两个住在不同房子里的人,要说话得靠“电话线”(通信API),要是没这根线,再大声喊也没用。

我去年帮朋友解决问题时,一开始也没搞懂这点,直接在原生页面给Webview的H5页面赋值变量,结果当然是没反应——后来查uni-app官方文档才明白,通信的核心是“消息传递”:原生页面把数据包装成“消息”,通过通信API发给H5页面;H5页面把消息“拆包”,处理后再包装成新消息发回去。这就像两个人发短信,得有“短信平台”(官方通信API),还得遵守“短信格式”(JSON)。

再举个例子:你在原生页面有个userInfo变量,想给Webview的H5页面用,直接传this.userInfo是不行的——得把userInfo转换成JSON字符串,通过通信API发过去,H5页面再把JSON字符串解析成对象才能用。去年朋友的问题,就是没做“转换”这一步,结果H5页面收到的参数全是“乱码”。

手把手教你实现双向通信:从配置到示例全流程

搞懂逻辑后,接下来直接上干货——我把双向通信拆成“配置Webview→原生发消息给H5→H5发消息给原生”三个步骤,每步都附可复制的示例代码,连去年帮朋友做的“商品ID传递”示例都放进去了。

第一步:先把Webview组件配置对

要通信,得先让Webview“能被调用”。在原生页面的Vue文件里写Webview组件时,一定要加ref属性(给Webview起个“名字”),还要加onLoad事件(监听Webview加载状态):


<!-

  • ref="myWebview" 是给Webview起名字,方便后面调用方法 >
  • <!-

  • onLoad="onWebviewLoad" 监听Webview加载完成事件 >
  • export default {

    data() {

    return {

    webviewUrl: 'https://你的H5页面地址' // 替换成你的H5页面URL

    }

    },

    methods: {

    onWebviewLoad() {

    console.log('Webview加载完成,可以发消息了');

    }

    }

    }

    为什么要加ref?因为后面要调用Webview的postMessage方法(发消息),得通过this.$refs.myWebview找到这个Webview组件。为什么要监听onLoad?因为Webview没加载完成时,发消息会“石沉大海”——去年朋友就是没加这个事件,直接在onLoad生命周期发消息,结果H5页面收不到。

    第二步:原生页面给H5页面发消息

    原生给H5发消息,用uni-app官方推荐的uni.webView.postMessage方法(别自己写JSBridge,不稳定)。比如你要给H5页面传商品ID123,代码是这样的:

    // 原生页面的methods里加发消息的方法
    

    sendMessageToH5() {

    //

  • 把要传的参数包装成JSON(避免乱码)
  • const goodsInfo = JSON.stringify({ goodsId: '123' });

    //

  • 调用Webview的postMessage方法发消息
  • this.$refs.myWebview.postMessage({

    data: {

    content: goodsInfo // 消息内容,必须放在data里

    }

    });

    }

    然后在onWebviewLoad事件里调用这个方法——确保Webview加载完成后再发:

    onWebviewLoad() {
    

    this.sendMessageToH5(); // Webview加载完成后发消息

    }

    接下来是H5页面的接收逻辑——在H5页面的JS里,要加window.addEventListener('message')监听消息:

    // H5页面的JS代码(比如放在script标签里)
    

    window.addEventListener('message', function(event) {

    //

  • 接收原生发来的消息
  • const message = event.data;

    //

  • 解析JSON字符串(和原生发的时候对应)
  • const goodsInfo = JSON.parse(message.content);

    //

  • 用解析后的参数做事情(比如调用接口获取商品详情)
  • console.log('收到原生传来的商品ID:', goodsInfo.goodsId); // 输出123

    getGoodsDetail(goodsInfo.goodsId); // 调用接口获取商品详情

    });

    这里要注意两点:①event.data是原生发过来的消息对象,里面的content是我们包装的JSON字符串;②一定要用JSON.parse解析——去年朋友就是没做这一步,结果H5页面收到的goodsId是乱码。

    第三步:H5页面给原生页面发消息

    反过来,H5页面要给原生发消息,得先引入uni-app的Webview SDK(因为H5页面没有uni-app的环境,得手动加SDK才能调用API)。在H5页面的里加这段代码:

    <!-
  • 引入uni-app的Webview SDK,确保在其他JS之前加载 >
  • 然后在H5页面里写发消息的逻辑——比如用户点击“收藏商品”后,把商品ID传给原生页面:

    // H5页面的“收藏”按钮点击事件
    

    handleCollect() {

    const collectInfo = {

    goodsId: '123',

    isCollected: true

    };

    // 调用uni.postMessage发消息给原生

    uni.postMessage({

    data: collectInfo // 要传的参数

    });

    }

    原生页面接收消息的逻辑——在Webview组件上加@message事件

    
    

    export default {

    methods: {

    onReceiveMessage(event) {

    // 接收H5发来的消息(event.detail.data是消息数组,取第一个元素)

    const collectInfo = event.detail.data[0];

    console.log('H5传来的收藏信息:', collectInfo); // 输出{ goodsId: '123', isCollected: true }

    // 做后续处理(比如更新原生页面的收藏状态)

    this.updateCollectStatus(collectInfo);

    }

    }

    }

    这里要注意:event.detail.data是一个数组,因为uni-app的Webview会把多条消息存在队列里,所以要取第一个元素([0])。去年帮朋友做的时候,他一开始没加[0],结果拿到的是数组,没法直接用——这点一定要记牢!

    避坑指南:常见问题的解决办法

    就算按上面的步骤做,也可能碰到一些“小意外”——我把去年踩过的坑整理成了表格,直接对照解决就行:

    问题场景 原因分析 解决方法
    原生发消息H5收不到 Webview未加载完成就发消息 把发消息的代码放在Webview的@load事件里,或加1秒延迟(setTimeout)
    H5发消息原生收不到 H5页面没引入uni.webview.js SDK 在H5页面的里加SDK引用(看第三步的代码)
    参数乱码/解析失败 未对参数做JSON序列化 原生发消息前用JSON.stringify,H5接收后用JSON.parse
    微信小程序里消息延迟 微信小程序的Webview.postMessage会缓存消息 发消息后延迟500ms再切换页面(用setTimeout)

    比如去年朋友碰到的“参数乱码”问题,就是没做JSON序列化——他直接传goodsId: '123',结果H5页面收到的是"123"(带引号的字符串),没法直接用;后来加了JSON.stringifyJSON.parse,立刻就好了。

    按上面的步骤走,不管是原生给H5传参数,还是H5给原生反馈操作,应该都能搞定了。要是你试的时候碰到某个步骤卡壳,比如示例代码运行不起来,或者消息还是收不到,欢迎在评论区留个言——毕竟我踩过的坑比你吃过的泡面还多,总能帮你找到解决办法!


    本文常见问题(FAQ)

    为什么uni-app里Webview和原生页面不能直接传变量

    因为Webview本质是嵌套在原生页面里的H5容器,相当于两个完全隔离的环境——原生页面用的是uni-app的Vue框架,H5页面用的是浏览器的JS环境,两者的数据、变量都不互通,就像两个住在不同房子里的人,得靠“消息传递”这个“电话线”才能交流,直接传变量肯定没反应。

    Webview组件配置时为什么一定要加ref属性

    ref属性是给Webview起个“名字”,后面要调用Webview的postMessage方法发消息时,得通过这个“名字”找到对应的组件。比如你要给H5发商品ID,得用this.$refs.myWebview.postMessage才行,要是没加ref,根本找不到这个Webview,消息肯定发不出去。

    原生给H5发消息时,为什么要把参数转成JSON字符串

    因为原生和H5是不同的环境,直接传对象或变量会出现“格式不兼容”的问题,比如去年我朋友直接传goodsId,H5收到的是乱码。转成JSON字符串相当于把参数“打包”,H5页面再用JSON.parse“拆包”,才能正确拿到里面的内容,保证参数不丢失、不乱码。

    H5给原生发消息前,必须做什么准备

    H5页面得先引入uni-app的Webview SDK,就是在

    里加一段的代码。没有这个SDK,H5页面没法调用uni.postMessage方法,原生页面根本收不到消息——我之前帮朋友调bug时,就碰到过他漏加SDK导致消息发不出去的情况。

    微信小程序里Webview发消息总延迟,怎么办

    微信小程序的Webview.postMessage方法会缓存消息,所以发消息后可以加个500ms的延迟再切换页面,比如用setTimeout(() => { / 切换页面的代码 / }, 500)。这样能确保消息已经传送到原生页面,不会出现延迟或丢失的情况,我去年在微信小程序里试这个方法,效果挺好的。

    原文链接:https://www.mayiym.com/51939.html,转载请注明出处。
    0
    显示验证码
    没有账号?注册  忘记密码?

    社交账号快速登录

    微信扫一扫关注
    如已关注,请回复“登录”二字获取验证码