拓冰建站拓冰建站
首页 / 资讯中心 / 正文

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

文章目录前言案例的结构重点完整代码先把两条调用方向讲透方向一ArkUI 调 JavaScript方向二JavaScript 调 ArkUIjsResult 这个状态为什么要留着双向通信流程可以怎么理解关键代码怎么迁移到真实业务安全提醒不是装饰这个案例适合的真实场景常见坑我提前说几个写在最后前言一旦Web组件不只是拿来“展示网页”事情就开始复杂了。活动页想调用原生分享H5 想拿登录态原生按钮想通知网页切 tab最后都会落到一个词上桥接。这个话题一上来就讲实现细节往往很容易把人讲懵。因为桥接不是一个 API而是一套通信关系。案例这一页的价值就在这它没有急着写满接口而是先把 ArkUI 和网页之间的调用方向讲清楚。说白了你得先知道谁调用谁再谈怎么调用。案例的结构重点案例把桥接拆成了三部分ArkUI 调 JavaScriptJavaScript 调 ArkUI双向通信的完整流程同时它还放了一个最小状态jsResult用来观察交互后的结果变化。这个思路是对的因为桥接这种东西如果没有一个状态出口很难确认链路到底通没通。完整代码import{DEMO_BG_COLOR,DEMO_CARD_COLOR,DEMO_THEME_COLOR,DEMO_SUBTEXT_COLOR}from./typesEntryComponentstruct WebJavaScriptBridge{StateisShow:booleantrueStatejsResult:string等待调用...callJsDemo():void{this.jsResultJS 调用结果:${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.jsResultJS 调用结果:${Date.now()}}这不是为了做花活而是为了让桥接变得可观测。桥接出问题时最麻烦的是你经常不知道卡在哪一段。是按钮没点到是原生方法没执行还是网页没回传只要你在页面里保留一个明确的结果显示区调试效率会高很多。双向通信流程可以怎么理解案例把完整流程总结成三步1.ArkUI 调用runJavaScript()执行JS2.JS通过 window.ohosCallNative()回调3.注册 javaScriptProxy 实现双向调用这三句本质上讲的是一件事原生和网页都不能把对方当成本地函数直接调用中间需要一个约定好的桥。你可以把它理解成一套跨边界协议。原生发消息过去网页按约定的方法名和参数处理网页再回消息回来原生按同样约定接住。真正麻烦的不是调用本身而是调用协议是否稳定。关键代码怎么迁移到真实业务如果你要落地到项目里建议最开始只定义少量桥接动作不要一口气开放十几个接口。一个靠谱的做法是先约定统一的数据格式比如{ action, payload }让原生只暴露少数可控动作比如分享、登录态获取、页面关闭对所有来自网页的数据做校验不要直接信任桥接的核心不是“能调通”而是“可控、可维护、可排查”。这点很重要。安全提醒不是装饰案例最后专门给了安全区这一点非常对。Text(使用 javaScriptProxy 时注意安全)Text(避免注入恶意代码和 XSS 攻击)Text(验证所有 JS 回调的数据合法性)很多人做桥接只关注功能结果把网页当成绝对可信。只要外部内容来源稍微复杂一点这种思路就会出事。至少要守住三条底线第一不要执行未经约束的任意脚本。第二不要把敏感能力全部开放给网页。第三所有回调参数都要校验格式和内容不能拿来就用。这个案例适合的真实场景活动页分享、H5 支付结果通知、内容页唤起原生评论区、嵌入式管理后台、Hybrid 登录流这些都是桥接高频场景。尤其当你项目里一部分页面是网页、一部分页面是原生时桥接能力几乎绕不过去。区别只在于你是先把它设计清楚还是后面边补边救火。常见坑我提前说几个第一个坑是直接把方法名和参数写死在多个页面里。后面一改协议所有地方一起炸。第二个坑是桥接动作没有日志。调试时只看到“没反应”但不知道消息有没有发出去。第三个坑是把桥接当成万能方案。很多高频交互如果可以原生化长期看还是原生更稳。第四个坑是没有设计调用失败的兜底。网页调原生失败、原生调网页失败都应该有明确反馈。写在最后桥接这件事最怕的不是复杂而是含糊。只要你先把方向分清楚再把协议和安全边界收紧它其实就是一套可以逐步扩展的通信层。这个案例最适合拿来当认知起点。你不一定今天就把完整桥接写完但至少从现在开始原生和网页之间那条线不会再是一团雾了。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门