当前位置: 首页 > news >正文

HarmonyOS7 原生和网页怎么互调:WebJavaScriptBridge 双向通信入门

文章目录

      • 前言
      • 案例的结构重点
      • 完整代码
      • 先把两条调用方向讲透
        • 方向一:ArkUI 调 JavaScript
        • 方向二:JavaScript 调 ArkUI
      • `jsResult` 这个状态为什么要留着
      • 双向通信流程可以怎么理解
      • 关键代码怎么迁移到真实业务
      • 安全提醒不是装饰
      • 这个案例适合的真实场景
      • 常见坑我提前说几个
      • 写在最后

前言

一旦Web组件不只是拿来“展示网页”,事情就开始复杂了。活动页想调用原生分享,H5 想拿登录态,原生按钮想通知网页切 tab,最后都会落到一个词上:桥接。

这个话题一上来就讲实现细节,往往很容易把人讲懵。因为桥接不是一个 API,而是一套通信关系。案例这一页的价值就在这,它没有急着写满接口,而是先把 ArkUI 和网页之间的调用方向讲清楚。

说白了,你得先知道谁调用谁,再谈怎么调用。

案例的结构重点

案例把桥接拆成了三部分:

  • ArkUI 调 JavaScript
  • JavaScript 调 ArkUI
  • 双向通信的完整流程

同时,它还放了一个最小状态jsResult,用来观察交互后的结果变化。这个思路是对的,因为桥接这种东西,如果没有一个状态出口,很难确认链路到底通没通。

完整代码

import{DEMO_BG_COLOR,DEMO_CARD_COLOR,DEMO_THEME_COLOR,DEMO_SUBTEXT_COLOR}from'./types'@Entry@Componentstruct WebJavaScriptBridge{@StateisShow:boolean=true@StatejsResult:string='等待调用...'callJsDemo():void{this.jsResult=`JS 调用结果:${Date.now()}`}build(){Column(){if(this.isShow){Scroll(){Column({space:16}){Text('Web JavaScript 交互').fontSize(16).fontColor(DEMO_THEME_COLOR).fontWeight(FontWeight.Bold)Column(){Text('JS Bridge 交互模式').fontSize(13).fontColor('#4D96FF').margin({bottom:10})Column({space:12}){Column(){Text('方向一: ArkUI -> JS').fontSize(12).fontColor('#4D96FF').fontWeight(FontWeight.Bold)Column(){Text('controller.runJavaScript(code)').fontSize(11).fontColor('#FFFFFF')}.width('100%').height(40).backgroundColor('#4D96FF').borderRadius(6).justifyContent(FlexAlign.Center)}Column(){Text('方向二: JS -> ArkUI').fontSize(12).fontColor('#FFA500').fontWeight(FontWeight.Bold)Column(){Text('.onControllerAttached() 注册 JS 回调').fontSize(11).fontColor('#FFFFFF')}.width('100%').height(40).backgroundColor('#FFA500').borderRadius(6).justifyContent(FlexAlign.Center)}Column(){Text('双向通信流程').fontSize(12).fontColor('#6BCB77').fontWeight(FontWeight.Bold)Column({space:4}){Text('1. ArkUI 调用 runJavaScript() 执行 JS').fontSize(10).fontColor('#FFFFFFCC')Text('2. JS 通过 window.ohosCallNative() 回调').fontSize(10).fontColor('#FFFFFFCC')Text('3. 注册 javaScriptProxy 实现双向调用').fontSize(10).fontColor('#FFFFFFCC')}.width('100%').backgroundColor('#6BCB77').borderRadius(6).padding(8)}}}.backgroundColor(DEMO_CARD_COLOR).padding(12).borderRadius(12)Column({space:8}){Text('交互结果展示').fontSize(14).fontColor(DEMO_THEME_COLOR).fontWeight(FontWeight.Bold)Text(this.jsResult).fontSize(13).fontColor('#1A1A1A')Button('模拟 JS 调用').onClick(()=>{this.callJsDemo()}).fontSize(12).backgroundColor(DEMO_THEME_COLOR)Button('模拟 runJavaScript').onClick(()=>{this.jsResult='执行 JS: changeTitle("New Title")'}).fontSize(12).backgroundColor('#6BCB77')}.backgroundColor('#E8F4FD').padding(14).borderRadius(12)Column({space:4}){Text('安全注意事项').fontSize(13).fontColor('#FF6B6B')Text('使用 javaScriptProxy 时注意安全').fontSize(12).fontColor('#333333')Text('避免注入恶意代码和 XSS 攻击').fontSize(12).fontColor('#333333')Text('验证所有 JS 回调的数据合法性').fontSize(12).fontColor('#333333')}.width('100%').backgroundColor('#FFF0F0').padding(12).borderRadius(8)}.width('100%')}}Text('WebJavaScriptBridge - JS Bridge 通信').fontSize(12).fontColor(DEMO_SUBTEXT_COLOR).margin({top:12})}.width('100%').height('100%').backgroundColor(DEMO_BG_COLOR).padding(16)}}

先把两条调用方向讲透

这部分是整篇最重要的认知点。

方向一:ArkUI 调 JavaScript

这是最容易理解的一条链路。原生侧通过控制器执行网页里的 JS 代码:

controller.runJavaScript(code)

比如网页里有个changeTitle(),那原生按钮就可以主动触发它。这个能力特别适合什么场景?

很典型的一类,是原生操作区控制网页内容。比如原生头部点“切换主题”“打开弹层”“跳到某个 section”,页面主体其实是 H5,这时候就要用原生去调 JS。

方向二:JavaScript 调 ArkUI

反过来,网页也可能需要告诉原生侧一些事情。比如:

  • H5 登录完成,通知原生刷新用户信息
  • 点击网页里的分享按钮,唤起原生分享面板
  • H5 页面里的某个链接不是普通跳转,而是触发原生路由

案例里用这句描述得比较抽象:

.onControllerAttached()注册JS回调

真实项目里,核心思想就是把一个可调用的原生接口暴露给网页脚本。网页拿到之后,就能带着参数回调原生。

jsResult这个状态为什么要留着

案例用@State jsResult保存交互结果:

@StatejsResult:string='等待调用...'

然后在点击按钮后更新它:

callJsDemo():void{this.jsResult=`JS 调用结果:${Date.now()}`}

这不是为了做花活,而是为了让桥接变得可观测。

桥接出问题时,最麻烦的是你经常不知道卡在哪一段。是按钮没点到?是原生方法没执行?还是网页没回传?只要你在页面里保留一个明确的结果显示区,调试效率会高很多。

双向通信流程可以怎么理解

案例把完整流程总结成三步:

1.ArkUI 调用runJavaScript()执行JS2.JS通过 window.ohosCallNative()回调3.注册 javaScriptProxy 实现双向调用

这三句本质上讲的是一件事:原生和网页都不能把对方当成本地函数直接调用,中间需要一个约定好的桥。

你可以把它理解成一套跨边界协议。

原生发消息过去,网页按约定的方法名和参数处理;网页再回消息回来,原生按同样约定接住。真正麻烦的不是调用本身,而是调用协议是否稳定。

关键代码怎么迁移到真实业务

如果你要落地到项目里,建议最开始只定义少量桥接动作,不要一口气开放十几个接口。

一个靠谱的做法是:

  • 先约定统一的数据格式,比如{ action, payload }
  • 让原生只暴露少数可控动作,比如分享、登录态获取、页面关闭
  • 对所有来自网页的数据做校验,不要直接信任

桥接的核心不是“能调通”,而是“可控、可维护、可排查”。这点很重要。

安全提醒不是装饰

案例最后专门给了安全区,这一点非常对。

Text('使用 javaScriptProxy 时注意安全')Text('避免注入恶意代码和 XSS 攻击')Text('验证所有 JS 回调的数据合法性')

很多人做桥接只关注功能,结果把网页当成绝对可信。只要外部内容来源稍微复杂一点,这种思路就会出事。

至少要守住三条底线:

第一,不要执行未经约束的任意脚本。

第二,不要把敏感能力全部开放给网页。

第三,所有回调参数都要校验格式和内容,不能拿来就用。

这个案例适合的真实场景

活动页分享、H5 支付结果通知、内容页唤起原生评论区、嵌入式管理后台、Hybrid 登录流,这些都是桥接高频场景。

尤其当你项目里一部分页面是网页、一部分页面是原生时,桥接能力几乎绕不过去。区别只在于你是先把它设计清楚,还是后面边补边救火。

常见坑我提前说几个

第一个坑,是直接把方法名和参数写死在多个页面里。后面一改协议,所有地方一起炸。

第二个坑,是桥接动作没有日志。调试时只看到“没反应”,但不知道消息有没有发出去。

第三个坑,是把桥接当成万能方案。很多高频交互如果可以原生化,长期看还是原生更稳。

第四个坑,是没有设计调用失败的兜底。网页调原生失败、原生调网页失败,都应该有明确反馈。

写在最后

桥接这件事,最怕的不是复杂,而是含糊。只要你先把方向分清楚,再把协议和安全边界收紧,它其实就是一套可以逐步扩展的通信层。

这个案例最适合拿来当认知起点。你不一定今天就把完整桥接写完,但至少从现在开始,原生和网页之间那条线不会再是一团雾了。

http://www.cnnetsun.cn/news/3888604.html

相关文章:

  • 揭秘外贸主动营销网站建设:从被动等待到主动出击的全链路转化指南
  • 【关注可白嫖源码】--课程设计--毕业设计--springboot校园新闻发布系统[编号:project81008](案件分析)
  • Allegro PCB Contour模式:高效实现板边等距走线
  • 从PC到Mac:OpenCore黑苹果实战指南
  • 5大核心功能:跨平台GUI智能代理Mobile-Agent完全指南
  • UniApp视频播放开发全攻略:从基础组件到原生插件避坑实践
  • 广东省惠州市淡水五层老房改造,卫生间改井道,钢板折弯轻奢定制家用电梯落地案例
  • 抖音批量下载神器:技术架构深度解析与实战指南
  • MySQL批量插入性能优化全攻略
  • 企业DCMM认证实战指南:从入门条件到高阶评估全解析
  • 深度解析网站建设和网页建设的区别:别再傻傻分不清,一篇讲透两者核心差异与价值
  • 20分钟实战A2A协议:构建可协作AI Agent系统的核心通信框架
  • Source Sans 3 字体深度解析:如何为现代UI设计构建专业字体系统
  • Windows 11任务栏拖放功能修复终极指南:3分钟快速恢复高效操作
  • 告别龟速下载!这款神器让你免费体验网盘高速下载的快乐
  • Ohook:3步免费解锁Microsoft 365完整功能终极指南
  • 混合董事会:AI如何重塑董事角色
  • SQL Server安装配置与核心管理工具指南
  • 瑞萨RA6M3 HMI开发板实战:从硬件加速到LVGL图形界面开发
  • 密云建设网站:为本地企业打造的真实口碑与专业落地指南
  • Unity开发必备:C#运算符与表达式核心指南
  • DAC数模转换器全解析:从Hi-Fi音频到嵌入式开发的核心原理与应用
  • 游戏实时翻译工具XUnity Auto Translator:原理、配置与实战指南
  • 第1讲:CatBase的代码编译
  • X-XSS-Protection头:从历史防御到现代弃用的安全演进
  • 工业级以太网PHY芯片CH182:从原理到硬件设计、软件调试全解析
  • 深度解析电子商务网站建设实训室简介如何助力新手零基础入门实操指南
  • 在M芯片Mac上运行iOS游戏的终极指南:PlayCover完全教程
  • 小白python入门 - 75. 综合实战
  • 02 — 三区模型:工作区、暂存区、仓库