Taro 鸿蒙技术内幕系列(三) - 多语言场景下的通用事件系统设计
基于 Taro 打造的京东鸿蒙 APP 已跟随鸿蒙 Next 系统公测,本系列文章将深入解析 Taro 如何实现使用 React 开发高性能鸿蒙应用的技术内幕
背景
在鸿蒙生态系统中,虽然原生应用通常基于 ArkTS 实现,但在实际研发过程中发现,使用 C++ 可以显著提升应用框架和业务的性能表现。随着鸿蒙系统的不断迭代升级,不同语言环境间的协作已成为不可或缺的开发范式,共同构建了更丰富的研发生态。
Taro 通过接入鸿蒙端的 C-API 相关能力,将组件、样式布局等运行时逻辑下沉到 C++ 层,从而极大地提升了页面的渲染性能。
在这样的背景下,构建一套在 C++、ArkTS 等不同语言环境之间高效通信的事件系统,成为了一个极具价值,对于 Taro 来说也是必修的课题。
多语言环境的事件处理机制
在 Harmony 端的适配过程中,事件系统扮演着双重角色:不仅驱动应用、页面和各模块组件的生命周期,还因为 ArkTS 和业务代码(JS)之间存在人为设定的界限,需要事件作为桥梁,以便 JS 能够调用 ArkTS 的原生能力。
跨语言环境事件驱动架构的设计考量
在设计跨语言环境的事件驱动架构时,需要同时考虑 ArkTS、JS 和 C++ 等多个语言环境的限制和运行时差异。如何实现事件在这些环境之间的有序传递,以驱动页面和组件的生命周期,是事件系统设计的重要考量。

通过 C++ 实现事件的底层逻辑,构建一个高效的事件管理系统,可以有效避免冗余接口的设计。同时,与鸿蒙的 C-API 支持的事件系统对接,将各类事件分发到不同语言环境,确保跨语言环境的事件分发与处理的有序性、高效性。

回顾 Taro 开始适配鸿蒙至今,事件系统也随之经历了从简单到完善的演进历程。从最初在 ArkTS 方案中的基础实现,到随着 Taro for Harmony 方案迭代发展,事件系统的设计也面临 ArkTS 带来的一些限制。
在 ArkTS 语言环境中事件架构的局限性
基于 ArkTS 语言环境实现的事件架构,在性能方面存在较大局限性。特别是在事件冒泡过程中,性能较差的语法,和回调逻辑可能会导致性能严重劣化,甚至阻塞主线程。这不仅会影响应用的响应速度,更有甚者可能对整体用户体验产生负面影响。

为了解决这些问题,提升性能以保证用户体验成为关键目标。通过将事件处理逻辑下沉到 C++ 层,并置于后台线程执行等优化手段。能够有效提高代码执行效率,同时避免逻辑阻塞主线程导致的延迟响应,以提升应用的流畅性,提供更佳的用户体验。

构建多语言环境下的事件系统
在构建多语言环境下的事件系统时,首要考虑各种类型的事件,比如:鸿蒙提供的组件通用事件、手势等。事件系统需要有效地管理这些不同的事件来源,并根据框架和用户的监听行为有序进行事件的分发。

在这些事件类型中,大致可以分为普通事件和节点事件两类。前者涵盖系统层面和应用、组件等生命周期的变化,通常由系统或应用状态的改变触发,主要由事件中心(eventCenter)来处理;节点事件则与 DOM Tree 紧密相关,这些事件通常需要快速响应,以确保用户界面的流畅性和交互的即时性。
事件中心(eventCenter)的实现
作为 Taro 运行时中的基础模块,事件中心专注于处理系统事件和生命周期。它允许框架和应用开发者在后台线程注册事件队列,并异步分发事件,从而有效减轻主线程的负担。事件中心能够快速响应各种事件,同时具备健壮的错误处理机制,帮助开发者快速定位和解决事件回调中的问题,从而提升开发效率和系统稳定性。
事件监听与分发
开发者可以在 C++ 和 ArkTS 等多种语言环境中创建事件监听器,并将相应的回调函数添加到事件队列中。这一机制允许开发者在不同的编程语言中灵活地定义和处理事件响应逻辑。
当事件触发时,会根据不同语言环境的运行时差异,将事件参数转换为对应的格式。这种参数转换确保了各语言环境能够正确理解并处理事件及包含的数据,无论是简单的数据类型还是复杂的对象结构,都能在不同语言之间无缝传递。

事件队列会根据监听器的类型,按照预定义的顺序,将事件分发到相应的语言环境中。这样一来,每个监听器都能在其所属的环境中高效地执行对应的回调函数。通过这种方式,不仅可以实现了跨语言的事件处理,优化事件的分发效率,并确保应用在响应用户交互时保持高性能和高稳定性。
需要注意的是,受限于底层限制,在 ArkTS 环境中注册的事件需要回到主线程执行,同时在鸿蒙端不支持 Symbol 类型的事件。
节点事件处理(domEvent)
在 HTML 中,节点事件处理流程会如下图所示,事件从根节点开始向下传播至目标节点,触发后再从目标节点顺着节点树向上冒泡。在鸿蒙端实现中,Taro 基于这一事件传播流程,为开发者提供一致的事件处理机制。
事件类型
在 Taro 框架中,节点主要处理三种类型的事件:鸿蒙事件、鸿蒙手势事件和自定义事件。这些事件都是从 TaroElement 上进行监听和触发的。根据事件的类型不同,节点会从相应的事件源设置 Receiver (事件接收器)来进行监听并处理回调逻辑。

鸿蒙事件和鸿蒙手势事件分别通过 RenderNode 注册到 Receiver,确保事件能够正确地传递和触发。而自定义事件则根据节点实现或用户自行触发,以满足各种不同类型的交互响应。
事件传播
当 TaroElement 上的事件被触发后,事件会沿着节点树向上传播。每个节点依次接收到事件,并执行相应的回调。执行完回调后,会检查开发者是否阻止冒泡,以决定是否继续向上传播。事件从目标节点开始,逐级往上直到根节点或者冒泡被阻止。

这允许开发者在事件传播过程中,通过任意节点处理或拦截事件来调整业务逻辑实现,以更灵活的方式在特定节点上执行逻辑,或通过阻止冒泡避免对上层节点的影响。这样的设计对于前端开发者来说,更加熟悉、直观。
鸿蒙系统的底层节点事件也有自己的传播逻辑,但由于其机制与
ArkNode节点树差异,为避免其事件干扰,需要阻止其冒泡行为并接管其传播流程,以确保事件传播与节点树正确关联。
事件回调
由于节点事件也需要回调 JS 环境中执行,根据事件类型的不同,按照 Web 标准将相应的节点、值和方法如 target、stopPropagation、value 等等挂载到事件对象上。通过执行当前回调的序列化方法,确保事件在不同语言环境传递时,可以保证其回调对象能力一致、参数完整。
在 C++ 中,许多组件依赖于事件机制来实现功能。例如,通过鸿蒙事件更新组件属性,还有各个组件节点间的事件传递等。这些组件利用事件机制来确保数据变化能够及时反映,并且用户交互能够顺利传递到系统的各个部分。
总结与展望
在多语言环境中,确保事件在不同语言环境传递时的一致性尤为重要,各个模块以及应用内不同页面或组件通过事件解耦驱动来提升可维护性。当前的解决方案有效提升了系统的响应速度和模块间的协作能力。
当下方案实现中仍然存在一些问题,比如早期通过事件绕过 ArkTS 与 JS 之间相互调用限制等场景,可以通过 TurboModule 来提供更加直接的调用方案。
未来,在 Taro for Harmony 场景下,各语言模块的协同将进一步增强。基于事件系统的设计,可以有效地解耦模块间逻辑,实现更灵活的组合。
相关文章:
Taro 鸿蒙技术内幕系列(三) - 多语言场景下的通用事件系统设计
基于 Taro 打造的京东鸿蒙 APP 已跟随鸿蒙 Next 系统公测,本系列文章将深入解析 Taro 如何实现使用 React 开发高性能鸿蒙应用的技术内幕 背景 在鸿蒙生态系统中,虽然原生应用通常基于 ArkTS 实现,但在实际研发过程中发现,使用 C…...
《Docker Registry(镜像仓库)详解》
一、引言 在容器化技术日益普及的今天,Docker 已成为众多开发者和企业的首选工具。而 Docker Registry(镜像仓库)作为 Docker 生态系统中的重要组成部分,负责存储和分发 Docker 镜像。本文将深入探讨 Docker Registry 的概念、功能…...
AI前景分析展望——GPTo1 SoraAI
引言 人工智能(AI)领域的飞速发展已不仅仅局限于学术研究,它已渗透到各个行业,影响着从生产制造到创意产业的方方面面。在这场技术革新的浪潮中,一些领先的AI模型,像Sora和OpenAI的O1,凭借其强大…...
超级详细讲解转义字符,\? \‘ \f \0 \t等等!!!
C语言有一组特殊的字符称作转义字符,顾名思义,转变原来的意思 1 \? ??)是一个三字母词,在以前的编译器它会被编译为] (??会被编译为[ 因此在以前输入(are you ok ??)就会被编译为are you ok ] 解决这个问题只要在问号前输入\…...
微信小程序数据请求教程:GET与POST请求详解
微信小程序数据请求教程:GET与POST请求详解 引言 在微信小程序的开发过程中,数据请求是至关重要的一部分。通过与后端服务器进行通信,小程序能够获取动态数据,实现丰富的功能。在这篇文章中,我们将深入探讨微信小程序中的数据请求,重点介绍GET和POST请求的使用方法、示…...
Linux系统管理基础指南--习题
目录 一、基础知识与命令 二、 Linux的用户接口 三、文件权限与目录管理 四、shell相关知识 五、软件安装与网络 六、网络进程管理 一、基础知识与命令 1. (操作题)分别执行下述命令 ls -al cd ~ cd man -f man man –k cd man --help cal --help date --help bc --he…...
JVM(JAVA虚拟机)内存溢出导致内存不足,Java运行时环境无法继续
1、先贴出服务最后打印出来的日志,意思就是给虚拟机分配的内存被用完了,没有可用的内存了,服务运行不了了,被动停服了。详细的日志记录在了/home/user/zx/tomcat/apache-tomcat-8.5.82/bin/hs_err_pid147951.log文件里。 Java Ho…...
IOC控制反转详解
IOC(控制反转) component的衍生注解 前面曾经提到,若想要把某个对象交给IOC容器管理,就需要在其声明上加上Component注解。但是Spring中有三层架构,为了更加清晰的标注对象是属于哪一层的,提供了三个Comp…...
Qml-TabBar类使用
Qml-TabBar类使用 TabBar的概述 TabBar继承于Container 由TabButton进行填充,可以与提供currentIndex属性的任何容器或布局控件一起使用,如StackLayout 或 SwipeView;contentHeight : real:TabBar的内容高度,用于计算标签栏的隐…...
C# 常量
文章目录 前言一、整数常量(一)合法与非法实例对比(二)不同进制及类型示例 二、浮点常量三、字符常量四、字符串常量五、定义常量 前言 在 C# 编程的世界里,常量是一类特殊的数据元素,它们如同程序中的 “定…...
diffusion model: prompt-to-prompt 深度剖析
参考:diffusion model(十四): prompt-to-prompt 深度剖析-CSDN博客 P2P提出的Motivation 目前大火的文生图技术(text to image),给定一段文本(prompt)和随机种子,文生图模型会基于这两者生成一张图片。生…...
uniapp实现APP版本升级
App.vue 直接上代码 <script>export default {methods: {//APP 版本升级Urlupload() {// #ifdef APP-PLUSplus.runtime.getProperty(plus.runtime.appid, (info) > {// 版本号变量持久化存储getApp().globalData.version info.version;this.ToLoadUpdate(info.versi…...
uniapp强制修改radio-group内单选组件的状态方法
在uniapp开发中,需要在radio-group内部切换时做判断,提醒客户是否要变换radio的值,但是大家知道radio是单选组件,往往你点击后,是不能再修改状态的,就算你在点击后做判断,修改current的值&#…...
学习python的第十四天之函数——高阶函数和偏函数
学习python的第十四天之函数——高阶函数和偏函数 高阶函数 高阶函数是指那些可以接受一个或多个函数作为参数,或者返回一个函数作为结果的函数。高阶函数是函数式编程范式中的一个重要概念,它们使得代码更加灵活和模块化。 sorted() sorted()函数用于对…...
数据结构之二叉树详解:从原理到实现
1. 什么是二叉树? 二叉树(Binary Tree)是一种树形数据结构,其中每个节点最多有两个子节点,分别被称为左子节点和右子节点。二叉树可以用来表示层次关系,如文件目录、组织结构,或用于快速查找、…...
iOS 系统中使用 webView 打印 html 的打印边距问题
需求是使用系统提供的打印功能将HTML代码打印出来 1、使用CSS page 设置边距(iOS不生效) page {margin: 0;padding: 0;size: A6 portrait; }在 Android 中边距设置生效的,但是在 iOS 系统使用CSS page规则是不生效的 当从 iOS 系统打印网页…...
如何在ubuntu上调试core dump
启用core dump 确认ulimit 状态 ulimit -c 如果输出是0,表示core dump被禁用了 运行 ulimit -c unlimited 再次运行 ulimit -c 确认输出是ulimited 设置core dump路径和文件名格式 下面命令表示设置core dump文件在当前目录(%e表示程序名&#x…...
基于 JNI + Rust 实现一种高性能 Excel 导出方案(上篇)
每个不曾起舞的日子,都是对生命的辜负。 ——尼采 一、背景:Web 导出 Excel 的场景 Web 导出 Excel 功能在数据处理、分析和共享方面提供了极大的便利,是许多 Web 应用程序中的重要功能。以下是一些典型的场景: 数据报表导出&am…...
【Maven】依赖管理
4. Maven的依赖管理 在 Java 开发中,项目的依赖管理是一项重要任务。通过合理管理项目的依赖关系,我们可以有效的管理第三方库,模块的引用及版本控制。而 Maven 作为一个强大的构建工具和依赖管理工具,为我们提供了便捷的方式来管…...
springboot/ssm高校超市管理系统Java商品出入库供应商管理系统web源码wms
springboot/ssm高校超市管理系统Java商品出入库供应商管理系统web源码wms 基于springboot(可改ssm)vue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库&a…...
Linux内核进程创建与调度机制详解
Linux内核进程创建机制深度解析:从fork到进程调度1. 进程创建概述在Linux操作系统中,进程创建是通过fork系统调用实现的。fork系统调用会创建一个与父进程几乎完全相同的子进程,包括代码段、数据段、堆栈等内存空间的复制。本文将深入分析Lin…...
stm32开发新手福音:告别复杂安装,用快马ai生成带详解的hal库基础代码
作为一名刚接触STM32开发的新手,我最近在尝试用HAL库控制GPIO时遇到了不少麻烦。从下载安装STM32CubeMX到配置工程,每一步都让我这个小白手忙脚乱。直到发现了InsCode(快马)平台,整个过程变得简单多了——不需要自己搭建环境,AI就…...
OpenClaw智能截图:nanobot自动识别图片中的文字信息
OpenClaw智能截图:nanobot自动识别图片中的文字信息 1. 为什么需要智能截图工具 在日常工作和学习中,我们经常遇到需要从图片中提取文字的场景。比如截取网页上的技术文档片段、保存会议白板上的讨论要点、或者整理纸质书籍中的关键段落。传统做法是手…...
大模型落地必看:蒸馏、微调、RAG全解析,案例+对比助你快速选对!
做AI落地、大模型应用的朋友,大概率都有过这样的困惑: 想让大模型适配自己的业务,到底该用蒸馏、微调还是RAG? 三者听起来都差不多,都是“优化大模型”,但实际用法、成本、效果天差地别——用错了ÿ…...
3步深度配置Obsidian Copilot:打造专属AI知识工作流
3步深度配置Obsidian Copilot:打造专属AI知识工作流 【免费下载链接】obsidian-copilot A ChatGPT Copilot in Obsidian 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-copilot 在信息爆炸时代,知识工作者面临的最大挑战不是获取信息&am…...
如何通过3个步骤快速掌握BetaFlight黑匣子日志分析
如何通过3个步骤快速掌握BetaFlight黑匣子日志分析 【免费下载链接】blackbox-log-viewer Interactive log viewer for flight logs recorded with blackbox 项目地址: https://gitcode.com/gh_mirrors/bl/blackbox-log-viewer 你是否曾经在调试无人机飞行问题时感到束手…...
OpenClaw多场景实战:Qwen3-VL:30B在飞书中的5个应用案例
OpenClaw多场景实战:Qwen3-VL:30B在飞书中的5个应用案例 1. 为什么选择OpenClawQwen3-VL:30B组合 去年我在团队内部尝试搭建智能助手时,发现市面上大多数方案要么需要将敏感数据上传到第三方平台,要么功能过于单一。直到遇到OpenClaw这个开…...
Android开发避坑指南:registerForActivityResult找不到?可能是依赖版本惹的祸
Android开发实战:全面解析registerForActivityResult的正确使用与版本适配 在Android应用开发中,Activity之间的数据传递一直是核心功能之一。随着Jetpack组件的不断演进,Google推出了registerForActivityResult这一现代化API来替代传统的sta…...
CosyVoice Docker Compose 中 model_id 的高效配置与优化实践
最近在部署 CosyVoice 语音服务时,我发现 docker-compose.yml 文件里的 model_id 配置项,虽然看起来只是简单的一行,但配置得当与否,直接关系到整个服务的部署效率、启动速度和资源开销。如果随便填一个值,或者不理解其…...
3个场景解密LeagueAkari:如何让英雄联盟游戏效率提升300%
3个场景解密LeagueAkari:如何让英雄联盟游戏效率提升300% 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit LeagueAkari…...
