《HarmonyOSNext Web组件双向通信开发指南:JavaScript互调+动态注册+跨端数据流转实战》

简介: 本文详细讲解了HarmonyOS Next中Web组件的双向通信开发技巧,包括应用侧调用前端JS函数(`runJavaScript()`与`runJavaScriptExt()`)、注册应用方法到前端(初始化注册与动态注册)、参数传递实战(数组、对象、回调)及Promise异步交互等内容。通过具体代码示例,展示了如何实现跨端数据流转,并总结了常见问题及解决方法,帮助开发者高效掌握双向通信核心技能。适合教育科普行业学习参考。

《HarmonyOSNext Web组件双向通信开发指南:JavaScript互调+动态注册+跨端数据流转实战》

##Harmony OS Next ##Ark Ts ##教育

本文适用于教育科普行业进行学习,有错误之处请指出我会修改。

🚀 一、应用侧如何调用前端JS函数?

应用侧有两种神器可以调用前端页面的JavaScript函数:runJavaScript() 和它的升级版 runJavaScriptExt()!两者的核心区别是:

  • runJavaScript():只能传字符串类型的脚本
  • runJavaScriptExt():更强更灵活!支持字符串和二进制数据(ArrayBuffer),还能用AsyncCallback异步获取结果!

📌 举个栗子:点击应用按钮让前端字体变绿!
当我们在应用侧点击"runJavaScript"按钮时,触发前端页面的htmlTest()方法:

💻 前端页面代码

<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">点我变魔术!</button>
<h1 id="text">原始黑色文字👉调用runJavaScript变绿🍀,runJavaScriptCodePassed变红🔥</h1>
<script>
    // 有参函数调用
    var param = "从ArkTS发来的消息:Hi JS!";
    function htmlTest(param) {
        document.getElementById('text').style.color = 'green';
        console.log(param); // 控制台打印参数
    }

    // 无参函数调用(和上面是同一个函数名演示不同场景)
    function htmlTest() {
        document.getElementById('text').style.color = 'green';
    }

    // 按钮触发桥接函数
    function callArkTS() {
        changeColor();
    }
</script>
</body>
</html>

⚙️ 应用侧ArkTS代码

// WebComponent.ets
import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();

  aboutToAppear() {
    // 开启Web调试模式(重要!)
    webview.WebviewController.setWebDebuggingAccess(true);
  }

  build() {
    Column() {
      Button('runJavaScript')
        .onClick(() => {
          // 调用无参版:去掉param
          this.controller.runJavaScript('htmlTest()'); 
        })

      Button('runJavaScriptCodePassed')
        .onClick(() => {
          // 直接注入JS代码片段
          this.controller.runJavaScript(
            `function changeColor(){
              document.getElementById('text').style.color = 'red'
            }`
          );
        })

      // 加载本地HTML页面
      Web({ 
        src: $rawfile('index.html'), 
        controller: this.controller 
      })
    }
  }
}

🔌 二、注册应用侧方法到前端

想让前端页面调用应用侧的方法?我们需要把ArkTS方法"注入"到前端!有两种神操作:

方式1:初始化时注册(超省心!)

// 初始化注册版.ets
import { webview } from '@kit.ArkWeb';

// 要注册的测试类
class TestAgent {
  test(): string {
    return 'ArkTS发来的问候!';
  }
}

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController();
  @State agent: TestAgent = new TestAgent(); // 注册对象

  build() {
    Column() {
      Button('卸载代理')
        .onClick(() => {
          this.controller.deleteJavaScriptRegister("agentName");
        })

      Web({ src: $rawfile('index.html'), controller: this.controller })
        // 核心注入操作!
        .javaScriptProxy({
          object: this.agent,
          name: "agentName",     // 前端通过该名称调用
          methodList: ["test"],  // 暴露的方法
          controller: this.controller
        })
    }
  }
}

方式2:动态注册(灵活但需手动刷新)

// 动态注册版.ets
import { webview } from '@kit.ArkWeb';

class DynamicAgent {
  greet(): string {
    return "ArkUI动态注册示例";
  }
}

@Entry
@Component
struct Index {
  controller: webview.WebviewController = new webview.WebviewController();
  @State agent: DynamicAgent = new DynamicAgent();

  build() {
    Column() {
      Button('刷新页面')
        .onClick(() => {
          this.controller.refresh(); // 注册后必须刷新生效!
        })

      Button('注册到前端')
        .onClick(() => {
          // 动态注册关键操作
          this.controller.registerJavaScriptProxy(
            this.agent, 
            "dynamicAgent",
            ["greet"] // 暴露的方法名
          );
        })

      Web({ src: $rawfile('index.html'), controller: this.controller })
    }
  }
}

⚡ 重要提示:动态注册后必须执行.refresh() 才能生效!


🧩 三、参数传递实战宝典

场景1:传递数组对象

// ArkTS侧
class ArrayAgent {
  getNumbers(): number[] {
    return [1, 3, 5, 7]; 
  }
}
<!-- 前端调用 -->
<script>
function getData() {
  const nums = testAgent.getNumbers();
  console.log("收到数组:", nums); // [1,3,5,7]
}
</script>

场景2:传递自定义对象

// 定义学生对象
class Student {
  name: string = '';
  age: number = 0;
}

class StudentAgent {
  getStudent(): Student {
    return { name: "小明", age: 18 }; 
  }
}
<script>
function showStudent() {
  const stu = studentAgent.getStudent();
  alert(`姓名:${stu.name},年龄:${stu.age}`);
}
</script>

场景3:双向回调神操作

// ArkTS接收JS回调
class CallbackAgent {
  handle(callback: (data:string) => void) {
    setTimeout(() => callback("操作完成!"), 1000);
  }
}
<script>
testAgent.handle((result) => {
  console.log("回调结果:", result); 
});
</script>

🔄 四、Promise异步交互

方式1:ArkTS返回Promise

class PromiseAgent {
  fetchData(): Promise<string> {
    return new Promise((resolve) => {
      setTimeout(() => resolve("获取成功"), 1500);
    });
  }
}
<script>
promiseAgent.fetchData()
  .then(data => console.log(data))
  .catch(err => console.error(err));
</script>

方式2:前端生成Promise

<script>
function asyncOperation() {
  return new Promise((resolve) => {
    testAgent.delayCallback(resolve); 
  });
}

asyncOperation().then(() => {
  console.log("异步操作完成!");
});
</script>

📊 避坑指南总结表

场景 易错点 解决方案
方法注册未生效 忘记调用.refresh() ✅ 注册后立即刷新页面
参数传递失败 类型不匹配 ✅ 用基础类型或JSON对象
Promise未执行 未正确处理异常 ✅ 添加.catch()捕获错误
内存泄漏 未注销注册对象 ✅ 页面关闭时deleteJavaScriptRegister
权限校验失败 permission配置错误 ✅ 参考官方JSON模板

💡 终极提示:调试时务必开启 setWebDebuggingAccess(true),配合Chrome DevTools实时查看控制台输出!


🎯 关键要点总结

  1. 双向通信三剑客
    runJavaScript() ➡️ 基础调用
    javaScriptProxy() ➡️ 初始化注册
    registerJavaScriptProxy() ➡️ 动态注册(记得refresh!)
  2. 数据传输四原则
    ✅ 基础类型直接传
    ✅ 对象用Class封装
    ✅ 数组自动序列化
    ✅ 函数通过回调传递
  3. 异步交互双通道
    Promise方案:适合明确操作结果的场景
    Callback方案:适合事件驱动型交互

最后放个彩蛋🥚:遇到permission配置头秃时,直接用官方提供的JSON模板改参数值就好啦!不需要自己造轮子~

相关文章
|
6月前
|
人工智能 算法 搜索推荐
付阳老师“七步闭环法”GEO优化标准作业程序(SOP)深度解析
在AI搜索重构营销的当下,付阳老师首创《七步闭环法》GEO优化体系:以用户真需求为本,紧扣AI检索逻辑与EEAT原则,覆盖诊断、关键词、资料库、选题、创作、发布、迭代全流程,助力企业内容成为DeepSeek、文心等AI工具的“标准答案”,实现低成本、高信任、强占位的精准获客。(239字)
|
10月前
|
安全 Java Android开发
深度解析 Android 崩溃捕获原理及从崩溃到归因的闭环实践
崩溃堆栈全是 a.b.c?Native 错误查不到行号?本文详解 Android 崩溃采集全链路原理,教你如何把“天书”变“说明书”。RUM SDK 已支持一键接入。
1806 290
|
API Android开发 数据安全/隐私保护
解决android webview 加载http url 失败 net::ERR_CLEARTEXT_NOT_PERMITTED 错误
解决android webview 加载http url 失败 net::ERR_CLEARTEXT_NOT_PERMITTED 错误
3816 0
|
开发工具
【HarmonyOS】鸿蒙应用蓝牙功能实现(一)
【HarmonyOS】鸿蒙应用蓝牙功能实现(一)
518 8
【HarmonyOS】鸿蒙应用蓝牙功能实现(一)
|
数据安全/隐私保护 Android开发 iOS开发
如何设置APN
设置APN(接入点名称,Access Point Name)是连接互联网或特定网络服务(如彩信、移动数据等)时,设备需要配置的一个重要参数。不同的手机操作系统(如Android、iOS)和不同的移动网络提供商(如中国移动、中国联通、中国电信等)可能有不同的设置步骤。以下是一些基本的步骤和注意事项,用于设置APN:
|
移动开发 前端开发 API
【HarmonyOS 5】鸿蒙应用px,vp,fp概念详解
目前的鸿蒙开发者,大多数是从前端或者传统移动端开发方向,转到鸿蒙应用开发方向。 前端开发同学对于开发范式很熟悉,但是对于工作流程和开发方式是会有不适感,其实移动应用开发与前端开发,最大的区别就在于UI适配和性能优化上了。 今天我们就来分析下鸿蒙中UI适配的规范与小窍门。
726 0
|
JavaScript Windows
Node Sass could not find a binding for your current environment: Windows 64-bit with Node.js 1x.x
Node Sass could not find a binding for your current environment: Windows 64-bit with Node.js 1x.x
861 0
|
Web App开发 编解码 移动开发
网页不安装插件如何播放RTSP/FLV视频
点量云流提出了一种基于后台拉流转码的方案,将RTSP/RTMP/FLV等协议的视频流转换为WebRTC格式,实现在现代浏览器中的无插件播放。此方案具有良好的兼容性,支持主流浏览器,无需担心兼容问题。它利用浏览器硬件解码能力,减少终端计算资源消耗,并且具备低延迟和高实时性的优点,延迟可控制在100ms以内,非常适合摄像头监控领域。此外,前端集成简单,仅需使用标准WebRTC接口即可接入,降低了复杂度。
1261 9
|
监控 Java Sentinel
Hystrix和Sentinel有什么异同
Hystrix 和 Sentinel 是提升微服务架构稳定性的流行组件,均支持服务熔断与限流,提供实时监控。Hystrix 通过线程池和信号量实现服务隔离,Sentinel 基于流量控制和系统负载保护,各有特色。
719 0
|
前端开发 数据可视化 项目管理
Dhtmlx Gantt教程:创建交互式甘特图的完整指南
Dhtmlx Gantt教程:创建交互式甘特图的完整指南

热门文章

最新文章