资讯动态

React Native鸿蒙跨平台入门:温度计Demo实战指南

发布时间:2026/9/10 0:05:18 来源:尧图企业网站定制
先说结论如果你已经会 React想试试鸿蒙端的跨平台开发做一个温度计 Demo 是性价比最高的入门方式。它不涉及复杂业务却能把你从“React Native 能不能跑在鸿蒙上”一直带到“跑起来之后怎么调试、怎么排查白屏、怎么处理状态更新”这条完整链路而且整个过程不需要碰原生代码。下面就是我实际跑通这个项目后整理的全过程。我选择“React Native 鸿蒙跨平台”这个方向并不是因为它能替代所有原生方案而是因为现在 React Native 的跨端能力已经天然覆盖了 Android、iOS再加上社区维护的鸿蒙适配层一套 JS 代码就有机会在三种系统上复用。对个人开发者来说这意味着可以少写两套 UI把精力留到业务逻辑上。对团队来说几套端上代码合并成一套维护成本会明显降下来。当然前提是你先接受“RN 业务层 原生宿主”这种架构思路。下面从项目设计、环境搭建、温度计实现、鸿蒙端部署、常见问题五个部分展开。整个内容都是我实际敲过、跑过、翻过车的记录不是纸面教程。1. 项目整体设计与思路拆解1.1 为什么选温度计作为入门案例温度计这个场景几乎把 React Native 入门必学的知识点都覆盖了组件树需要用到 View、Text、StyleSheet 这几个最基础的组件。状态管理温度值本身就是动态状态天然适合用 useState 保存。生命周期与副作用模拟传感器持续上报温度必须用 useEffect setInterval。样式计算温度条高度、滑块位置、颜色变化都需要按数值动态计算。跨端验证同一个组件在 Android 上能跑在鸿蒙上也能跑这就是跨平台开发最直接的体感。做个温度计而不是做 Todo List是因为温度计比 Todo List 更接近真实业务场景——真实业务里几乎处处是“动态数据驱动界面变化”。Todo List 多数时候是静态列表你感受不到“状态一改整个 UI 跟着变”的紧张感。温度计则每秒钟都在变化这能逼着你理解 React 的渲染机制。1.2 React Native 和鸿蒙的结合方式很多人第一次听到“React Native 鸿蒙跨平台”会以为是把 React Native 直接装进鸿蒙系统其实不是。准确说法是鸿蒙OpenHarmony 系这边有一个 React Native 的适配运行时它把 RN 的 JS 层和鸿蒙的 ArkUI 组件层桥接起来。你在 JS 里写的 View最终渲染出来的是鸿蒙原生的组件你在 JS 里管理的 state最终会以 ArkUI 的属性更新方式同步到界面上。打个比方React Native 像是有一套“通用 UI 翻译标准”Android 负责翻译成 Android 的 XMLiOS 翻译成 UIKit鸿蒙这边就翻译成 ArkUI 的组件结构。温度计这个 Demo 的所有界面代码都只用英文JS 语法写一遍然后分别交给不同的“翻译官”。社区里目前维护的鸿蒙适配层项目一般叫react-native-harmony这个方向。它支持通过特定模板初始化鸿蒙工程也能把现有 RN 工程“接”到鸿蒙宿主应用里。入门阶段不推荐碰原生桥接先把 JS 层的组件、状态、样式用熟后面再深入性能调优和自定义原生模块。1.3 技术选型为什么要这么定我的建议组合是React Native 0.72 或 0.73 版本的稳定分支 HarmonyOS SDKAPI 9 以上 TypeScript。原因有三个第一0.72 / 0.73 是社区适配鸿蒙时覆盖比较成熟的版本范围老版本不一定有对应的鸿蒙适配产物第二TypeScript 能帮你提前发现温度计算、样式属性这些数据类型错误尤其对新手特别友好第三API 9 以上的鸿蒙模拟器和真机生态比较完整不至于卡在环境问题上。有一点要提醒React Native 的社区生态和鸿蒙适配层的版本是深度绑定的不要自己随便升级 SDK 或 RN 大版本。我见过不少项目跑不起来都是因为用了太新的 React Native 版本而鸿蒙适配还没有跟上最后只能降级。选型的时候优先看适配仓库里明确标注的“支持版本范围”而不是追新。2. 环境准备与工程初始化2.1 你本地需要准备哪些东西先把工具链列出来省得你一边装一边缺Node.js 18 或 20 的 LTS 版本React Native 的脚手架和 Metro 打包器都依赖它。JDK 17RN 0.73 之后默认要求 JDK 17。Android Studio可以不装但装了方便你先在 Android 上验证工程是否正常。DevEco Studio这是鸿蒙侧的 IDE用来打开鸿蒙工程、连接模拟器或真机。鸿蒙 SDKAPI 9 以上和对应的模拟器镜像。装完之后先执行node -v npm -v java -version确认这三个命令都有输出再往下走。工程初始化阶段最忌讳一件事环境变量没配好然后报一个看不懂的错先在环境上耗掉一下午。2.2 初始化 React Native 工程并接入鸿蒙适配我实际操作时用的是社区提供的鸿蒙模板来初始化工程这样最省事。npx react-native-community/cli init RNThermometer --version 0.72.7 cd RNThermometer如果你的 CLI 版本较新也可以直接用npx react-native init。初始化之后这个工程默认是能跑 Android 和 iOS 的。先别急着加鸿蒙先在 Android 模拟器上跑一遍确认 React Native 基础链路没问题。这一步非常重要因为后面如果跑鸿蒙出现问题至少有 Android 作为对照能快速判断是业务代码问题还是鸿蒙适配问题。确认 Android 能跑起来之后再按鸿蒙适配仓库的说明把鸿蒙宿主工程相关文件导入进来。不同适配方案的操作有点差异我用的流程是把harmony目录放到工程根目录下然后在 DevEco Studio 里打开这个harmony目录作为鸿蒙工程再把 RN 生成的 JS Bundle 打包进鸿蒙应用里。这里有一个关键的工程结构认知鸿蒙端本质上是一个“壳工程”它的职责是加载 JavaScript Bundle并提供一个原生环境给 RN 渲染。温度计的业务代码全部在 JS 层鸿蒙壳工程里几乎不需要改逻辑。2.3 依赖安装的注意事项初始化好之后需要安装基础依赖npm install如果你的项目网络环境访问 npm 官方源比较慢可以用你所在公司或团队内部配置的 npm registry这里不展开。关键点是安装鸿蒙适配相关依赖时要以适配仓库文档中指定的包名为准不要自己从 GitHub 上随便拉一个分支来用。踩坑提醒安装依赖之后最好固定住package-lock.json不要频繁执行npm install覆盖依赖版本。React Native 加鸿蒙适配的依赖树非常敏感稍有不慎就会把某个原生模块版本搞乱导致编译期或者运行期报一堆莫名其妙的问题。3. 温度计界面实现从状态到 UI 的完整链路3.1 界面结构设计温度计的 UI 我拆成了四个部分温度数值显示一个大号的 Text。温度条一个垂直方向的“水银柱”内部高度随温度变化。温度刻度用于展示当前温度范围。一个滑块标记标出当前温度对应的位置。这四部分全是纯 JS 组件没有任何自定义原生模块。整个界面放在一个View里通过StyleSheet.create管理样式。这样做的好处是如果你之后想把这个 Demo 扩展成湿度计、气压计只需要改数据源和样式不用动工程结构。3.2 用 useState useEffect 模拟传感器温度温度计的灵魂在“数据不断变化”。真实硬件是通过传感器拿到温度这里我用setInterval模拟一个温度变化过程每 800ms 更新一次温度数值在 15 到 45 摄氏度之间浮动并且每次变化幅度控制在 ±1 度以内这样显示起来更自然。import React, { useEffect, useState } from react; import { StyleSheet, Text, View } from react-native; const MIN_TEMP 15; const MAX_TEMP 45; export default function Thermometer() { const [temperature, setTemperature] useState(26); useEffect(() { const timer setInterval(() { setTemperature(prev { const step Math.random() * 2 - 1; const next prev step; if (next MIN_TEMP) return MIN_TEMP; if (next MAX_TEMP) return MAX_TEMP; return Math.round(next * 10) / 10; }); }, 800); return () clearInterval(timer); }, []); return ( View style{styles.container} Text style{styles.tempText}{temperature.toFixed(1)}°C/Text Text style{styles.statusText}当前温度/Text /View ); } const styles StyleSheet.create({ container: { flex: 1, justifyContent: center, alignItems: center, backgroundColor: #f5f5f5, }, tempText: { fontSize: 72, fontWeight: bold, color: #333, }, statusText: { fontSize: 16, marginTop: 8, color: #777, }, });代码里面有几个细节值得说明setTemperature用了函数式更新因为下一次温度依赖上一次温度。如果你直接在外面读temperature然后加上一个随机数容易在定时器多次触发时读到旧值出现温度跳动异常。setInterval的清理函数一定要写。这个组件一旦卸载定时器不清理就可能在页面关闭后继续触发状态更新轻则警告重则崩溃。温度保留一位小数这样显示更有体温计的真实感。Math.round(next * 10) / 10是常见的保留一位小数写法避免直接用toFixed丢失数字类型精度。3.3 温度条和滑块动态百分比计算接下来是核心视觉效果一个竖条内部填充高度根据温度变化而变。先把整个温度范围 15~45 映射到 0%~100%。const percent ((temperature - MIN_TEMP) / (MAX_TEMP - MIN_TEMP)) * 100;这个百分比就是温度条内部填充区的高度也是滑块纵坐标的位置依据。滑块我用了一个绝对定位的小圆点通过bottom属性控制位置View style{styles.thermoBody} View style{[styles.thermoFill, { height: ${percent}% }]} / View style{[styles.thermoMarker, { bottom: calc(${percent}% - 8px) }]} / /View注意React Native 的样式里百分比写法在不同版本上的支持程度不一样。height: 50%这种是支持的但calc()支持力度一般。为了稳妥滑块位置我用绝对定位加偏移量计算成具体像素值而不是直接塞一个calc()进去否则可能在 Android 上没问题到了鸿蒙上就解析不了。算像素的做法是先给温度条一个固定高度THERMO_HEIGHT 260然后const markerBottom (percent / 100) * THERMO_HEIGHT - 8;8 是滑块半径的一半这样滑块的圆心刚好对准当前温度位置。3.4 温度颜色渐变用简单函数映射温度计还有一个细节是温度条颜色冷的时候是蓝色热的时候是红色。我写了一个函数根据温度在范围内的位置把 RGB 值从蓝色渐变到红色function getColor(percent: number) { const r Math.round((percent / 100) * 255); const g Math.round(80 (1 - Math.abs(percent - 50) / 50) * 100); const b Math.round(255 - (percent / 100) * 255); return rgb(${r}, ${g}, ${b}); }这个函数很基础但已经足够模拟“低温蓝、高温红”的直觉感受。实际项目里颜色映射可以做得很复杂比如引入色板库但入门阶段手动算 RGB 能帮你理解界面上的任何视觉变化本质上都是数据到样式的映射。3.5 完整组件拼装把所有部分拼在一起完整组件看起来类似这样export default function Thermometer() { const [temperature, setTemperature] useState(26); // ... useEffect 部分省略 const percent ((temperature - MIN_TEMP) / (MAX_TEMP - MIN_TEMP)) * 100; const markerBottom (percent / 100) * THERMO_HEIGHT - 8; const currentColor getColor(percent); return ( View style{styles.container} Text style{[styles.tempText, { color: currentColor }]} {temperature.toFixed(1)}°C /Text View style{[styles.thermoBody, { height: THERMO_HEIGHT }]} View style{[ styles.thermoFill, { height: ${percent}%, backgroundColor: currentColor }, ]} / View style{[styles.thermoMarker, { bottom: markerBottom }]} / /View View style{styles.scaleRow} Text style{styles.scaleText}{MIN_TEMP}°/Text Text style{styles.scaleText}{MAX_TEMP}°/Text /View /View ); }界面做完之后先在 Web 端或者 Android 模拟器上跑一遍确认界面长这样温度数字够大竖条高度随温度变化滑块跟着上下动颜色从蓝渐变到红。这部分验证通过再进入鸿蒙端部署环节。4. 鸿蒙端部署与调试从“能跑”到“跑顺”4.1 把 JS Bundle 打包进鸿蒙应用React Native 在开发阶段通常依赖 Metro dev server也就是说手机要从电脑上拉取 JS Bundle。这种方式在调试期很方便但到了鸿蒙真机上如果电脑不在身边或者网络不通应用就会一直白屏。所以部署到鸿蒙之前我先用打包命令把 JS Bundle 生成出来npx react-native bundle --platform harmony --dev false --entry-file index.js --bundle-output harmony/entry/src/main/resources/rawfile/index.jsbundle --assets-dest harmony/entry/src/main/resources/rawfile注意这里--platform harmony是鸿蒙适配层认识的自定义平台标识如果命令不支持这个参数说明适配层版本或方式不对需要看看对应模板的文档。Bundle 打出来之后启动鸿蒙应用时会直接加载rawfile里的 JS Bundle不依赖 Metro。这样应用在真机上也能正常启动不会出现“连不上开发服务器”的白屏。4.2 DevEco Studio 构建与运行用 DevEco Studio 打开工程里的harmony目录等待它同步依赖然后选择鸿蒙模拟器或真机运行。这里有几个我实际遇到的情况鸿蒙模拟器目前对 host 平台有要求。我当时用的模拟器镜像只支持 arm64 架构的设备后来改用真机测试反而更稳定。构建过程如果报“SDK 版本不匹配”去 DevEco 的 SDK Manager 里确认 API 版本是否和工程配置一致。第一次构建时间会比较长主要花在下载依赖和编译原生壳工程上耐心等不要中途关闭。运行成功之后你会看到鸿蒙应用里出现和 Android 一模一样的温度计界面温度持续刷新滑块和颜色跟着变化。这一刻你就已经把 React Native 的跨端能力真正落到了鸿蒙设备上。4.3 真机调试常用的日志命令如果应用跑起来之后界面没有正常显示或者温度不刷新最直接的办法是看日志。我用hdc连接真机查看应用输出hdc shell hilog | grep ReactNativeJS鸿蒙的日志系统叫hilogReact Native 运行时的 JS 日志会打到这里。看到类似Running RNThermometer with rootTag这样的输出说明 JS 运行时已经正常启动。如果什么都没有大概率是 Bundle 没加载对先把工程配置和打包路径再检查一遍。5. 常见问题与排查技巧实录5.1 React Native 启动白屏白屏是新手遇到最多的现象几乎可以排进“RN 鸿蒙开发劝退三连”。我自己的排查顺序是看 Metro 是否启动。开发模式下应用必须能访问开发服务器如果手机和电脑不在同一网络或者端口被占用就会白屏。最简单的验证办法是把 JS Bundle 打包到本地然后重新安装应用。看日志里有没有报 JS 异常。比如组件里某个属性写错、某个 API 在鸿蒙适配层还不支持都会导致渲染失败白屏。检查入口文件。index.js里注册组件名的字符串必须和应用宿主启动时要求的名称一致大小写都不能错。5.2 模拟器运行失败或无法安装如果你用鸿蒙模拟器报“运行设备不兼容”或者“只能在 arm64 平台运行”不用慌这是模拟器镜像对宿主架构的限制。解决思路有两个换一台 arm64 的电脑跑模拟器或者直接用鸿蒙真机调试。我当时的机子是 x86_64模拟器直接没法用切到真机之后一次就跑通了。5.3 温度不刷新或 UI 卡住如果界面静态显示温度不变化大概率是setInterval没有生效或者 JS 线程被卡住。先确认useEffect有没有正确注册定时器再看日志有没有Warning: Cant perform a React state update on an unmounted component之类的警告。如果是后台运行导致定时器被挂起可以把模拟传感器数据的逻辑改成一次性生成一组数据循环播放这样至少能看到界面变化。5.4 鸿蒙构建阶段报错速查我把最常见的几个构建错误整理成一张表方便你对照报错现象常见原因处理方式SDK version mismatchDevEco 配置的 API 版本和工程要求不一致在 SDK Manager 里安装对应版本oh_modules not found鸿蒙侧依赖没有同步在 DevEco 里重新 Sync 工程unable to resolve moduleJS 里引用了新依赖但 JS Bundle 未重新打包重新执行 bundle 命令signature error真机部署签名配置不正确检查自动签名或配置调试证书rn core component not found鸿蒙适配层没有包含对应组件检查适配层的版本和组件支持列表5.5 独家避坑千万别忽略锁版本这个项目踩过最大的坑是依赖版本不一致。React Native 本身迭代快鸿蒙适配层的发布节奏很难完全跟上。我之前试着把 RN 从 0.72 升到 0.73结果鸿蒙壳工程里有一个原生组件无法编译整个项目卡了两天。后来老老实实把版本降回适配层支持的区间一次通过。所以我的建议是把这个温度计 Demo 当做一个“冻结版本”的项目所有关键依赖都用精确版本号锁死不要随手npm update。等这个项目跑顺了再另外开分支升级版本验证完再合入这才是稳妥的玩法。最后说一点个人体会。这个温度计 Demo 看起来很小但跑通之后你对 React Native 的“状态驱动 UI”会有更深的肌肉记忆温度数据一变温度条高度跟着变滑块位置跟着变颜色跟着变这些变化不是靠手动操作 DOM 实现的而是 React 声明式渲染在替你干活。做鸿蒙跨平台开发也是这样重要的不是会写多少语法而是理解数据在 JS 层和原生层之间怎么流动。把这条链路打通以后不管换什么业务、什么设备你都不会慌。如果你把温度计跑通了下一步可以试试给温度计加一个“最高温/最低温”记录或者接入真实传感器数据。这个方向练下来你会把 React Native 的列表渲染、组件通信、原生模块调用都补齐那时候你已经不是入门选手了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价