
网罗开发 (小红书、快手、视频号同名)
大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方向。在移动端开发、鸿蒙开发、物联网、嵌入式、云原生、开源等领域有深厚造诣。
图书作者:《ESP32-C3 物联网工程开发实战》
图书作者:《SwiftUI 入门,进阶与实战》
超级个体:COC上海社区主理人
特约讲师:大学讲师,谷歌亚马逊分享嘉宾
科技博主:华为HDE/HDG
我的博客内容涵盖广泛,主要分享技术教程、Bug解决方案、开发工具使用、前沿科技资讯、产品评测与使用体验 。我特别关注云服务产品评测、AI 产品对比、开发板性能测试以及技术报告,同时也会提供产品优缺点分析、横向对比,并分享技术沙龙与行业大会的参会体验。我的目标是为读者提供有深度、有实用价值的技术洞察与分析。
展菲:您的前沿技术领航员
👋 大家好,我是展菲!
📱 全网搜索"展菲",即可纵览我在各大平台的知识足迹。
📣 公众号"Swift社区",每周定时推送干货满满的技术长文,从新兴框架的剖析到运维实战的复盘,助您技术进阶之路畅通无阻。
💬 微信端添加好友"fzhanfei",与我直接交流,不管是项目瓶颈的求助,还是行业趋势的探讨,随时畅所欲言。
📅 最新动态:2025 年 3 月 17 日
快来加入技术社区,一起挖掘技术的无限潜能,携手迈向数字化新征程!
文章目录
-
- 前言
- [Web 和 ArkTS 通信的核心思路](#Web 和 ArkTS 通信的核心思路)
- 一个最简单、但真实的使用场景
- [ArkTS 端:定义一个可注入的对象](#ArkTS 端:定义一个可注入的对象)
- [Web 组件中配置 javaScriptProxy](#Web 组件中配置 javaScriptProxy)
- [javaScriptProxy 配置项逐条解析](#javaScriptProxy 配置项逐条解析)
-
- object:真正被注入的对象
- [name:JS 侧访问的名字](#name:JS 侧访问的名字)
- methodList:允许被调用的方法白名单
- [controller:WebView 控制器](#controller:WebView 控制器)
- [JS 端:像调用普通对象一样调用 ArkTS](#JS 端:像调用普通对象一样调用 ArkTS)
- 同步调用适合用在什么地方
- 常见问题与踩坑经验
-
- [方法没暴露,JS 调用直接报错](#方法没暴露,JS 调用直接报错)
- [返回复杂对象,JS 拿不到](#返回复杂对象,JS 拿不到)
- 想做异步怎么办
- 把这套机制放进真实项目里
- 总结
前言
在鸿蒙应用里,只要你用过 Web 组件加载 H5 页面,基本都会绕不开一个问题:
H5 想直接调用 ArkTS 里的方法,该怎么做?
比如这些很典型的需求:
- H5 点了一个按钮,希望直接触发原生能力
- JS 想同步拿到设备信息、登录态、配置数据
- Web 页面和 ArkTS 页面需要"像在同一个世界"里通信
很多人第一反应是:
"是不是只能用异步回调?"
但实际上,鸿蒙 Web 组件已经给了一个非常直观的同步调用方式 ------javaScriptProxy。
这篇文章我们就从一个完整例子出发,把这套机制讲清楚。
Web 和 ArkTS 通信的核心思路
在鸿蒙 Web 组件中,javaScriptProxy 做的事情,本质上只有一件:
把 ArkTS 里的一个对象,按约定规则"注入"到 JS 运行环境中
注入完成后:
- JS 端可以像调用普通对象一样
- 同步调用 ArkTS 中的方法
- 不需要额外桥接代码、不需要消息回调
但前提是三点必须满足:
- ArkTS 端定义好"可暴露对象"
- 明确哪些方法允许 JS 调用
- Web 组件配置正确
下面我们一步一步拆。
一个最简单、但真实的使用场景
先设一个很常见的业务背景:
Web 页面是活动页
原生侧负责能力与数据
H5 需要直接拿到当前登录用户的 ID
这个场景特别适合用同步调用。
ArkTS 端:定义一个可注入的对象
第一步,是在 ArkTS 侧定义一个普通类,用来承载要暴露给 JS 的方法。
ts
class JsBridge {
getUserId(): string {
return 'user_10086'
}
showToast(msg: string): void {
console.info('来自 JS 的消息:' + msg)
}
}
这里有几个非常重要的点:
- 方法必须是同步方法
- 不要返回 Promise
- 返回值要是 JS 能理解的基础类型
建议一开始就把它当成:
"给 JS 用的工具类",
而不是业务 Service。
Web 组件中配置 javaScriptProxy
接下来是关键步骤,把这个对象"挂"到 Web 组件上。
ts
@Entry
@Component
struct WebPage {
controller: WebviewController = new WebviewController()
jsBridge: JsBridge = new JsBridge()
build() {
Web({
src: 'https://example.com',
controller: this.controller,
javaScriptProxy: {
object: this.jsBridge,
name: 'nativeBridge',
methodList: ['getUserId', 'showToast'],
controller: this.controller
}
})
}
}
这段代码里,每一项都很关键。
我们一条条拆。
javaScriptProxy 配置项逐条解析
object:真正被注入的对象
ts
object: this.jsBridge
- 就是刚才定义的
JsBridge - JS 实际调用的就是这个实例上的方法
name:JS 侧访问的名字
ts
name: 'nativeBridge'
- 这是 JS 侧能看到的对象名
- JS 会通过
window.nativeBridge来访问
这个名字,就是你给 JS 世界开的一个入口。
methodList:允许被调用的方法白名单
ts
methodList: ['getUserId', 'showToast']
这是很多人容易忽略的一点。
- 不在这个列表里的方法
- JS 是无法调用的
- 即使方法真实存在于对象中
这一步非常重要,它本质上是一个安全边界。
controller:WebView 控制器
ts
controller: this.controller
- 用于绑定当前 Web 实例
- 没它,代理不会生效
JS 端:像调用普通对象一样调用 ArkTS
当 Web 页面加载完成后,JS 侧可以直接这样写:
js
const userId = window.nativeBridge.getUserId()
console.log('当前用户ID:', userId)
window.nativeBridge.showToast('你好,ArkTS')
注意这里的几个特点:
- 是同步调用
- 有返回值
- 没有回调、没有 Promise
从 JS 的角度看,它完全不知道这是"原生方法"。
同步调用适合用在什么地方
很多人会问:
既然能同步,什么都用它行不行?
不太建议。
更合理的使用场景是:
- 获取配置类数据
- 获取登录态、环境信息
- 触发简单原生行为
不太适合的场景包括:
- 网络请求
- 耗时计算
- 涉及 IO 的操作
原因很简单:
同步调用一旦变慢,卡的是 Web 页面。
常见问题与踩坑经验
方法没暴露,JS 调用直接报错
九成是忘了加到 methodList。
这是最常见、也是最隐蔽的问题。
返回复杂对象,JS 拿不到
建议只返回:
- string
- number
- boolean
- 简单对象结构
复杂结构容易出现序列化问题。
想做异步怎么办
javaScriptProxy 不适合做异步。
如果需要异步通信,应该:
- 用 URL scheme
- 或者 Web 与 ArkTS 消息机制
把这套机制放进真实项目里
在实际项目中,我更推荐这样用:
- 一个专门的
JsBridge - 只放"跨端需要的能力"
- 控制方法数量
- 严格维护 methodList
把它当成:
ArkTS 与 H5 的"边界协议"
而不是随手塞逻辑的地方。
总结
javaScriptProxy 本身并不复杂,
复杂的,往往是我们没想清楚:
- 哪些能力该给 JS
- 哪些不该给
- 同步和异步的边界在哪里
一旦你把它当成"对象注入 + 方法白名单",
这套机制会非常顺手、也非常稳定。