本次项目参考大佬文章

https://blog.csdn.net/qq_74796274/article/details/155361907?spm=1001.2014.3001.5502

一、背景

编译运行鸿蒙项目,每次都需要"npm run dev"编译,拷贝编译出来的"bundle.harmony.js"到鸿蒙项目里,特别麻烦。生态融合需求:React(及其生态)拥有百万开发者与成熟方案,而鸿蒙(ArkUI)是新兴原生平台。通过技术适配,让React应用能运行在鸿蒙上,可极大降低鸿蒙应用开发门槛,加速生态繁荣。业务迭代刚需:为满足互联网业务快速迭代、紧急热修复和A/B测试的需求,避免传统应用商店审核的长周期,热更新能力成为鸿蒙商业化应用的必备技术栈。

如果不会搭建React鸿蒙环境的就看第一个链接。如果已经完成React的鸿蒙环境搭建的,请看第二个和第三个链接。如果还是看不懂,可以看看我这篇文章。

第一个链接:

https://blog.csdn.net/qq_74796274/article/details/155077369?spm=1001.2014.3001.5502

第二个链接:

https://blog.csdn.net/zl392321162/article/details/155355327

第三个链接:

https://blog.csdn.net/qiaomu8559968/article/details/155260449?spm=1001.2014.3001.5502

二、环境搭建

这里我是基于已经完成了我的React环境搭建,来进行的,如果没完成,请先完成React的鸿蒙环境搭建。

2.1修改metor.config.js文件

修改内容如下:

const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
const { createHarmonyMetroConfig } = require('@react-native-oh/react-native-harmony/metro.config');
/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = {
    transformer: {
        getTransformOptions: async () => ({
            transform: {
                experimentalImportSupport: false,
                inlineRequires: true,
            },
        }),
    }
};
 
module.exports = mergeConfig(
    getDefaultConfig(__dirname), 
    createHarmonyMetroConfig({
        reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
    }),
    config
);

2.2修改Index.ets文件

代码内容如下:

import {
  AnyJSBundleProvider,
  ComponentBuilderContext,
  FileJSBundleProvider,
  MetroJSBundleProvider,
  ResourceJSBundleProvider,
  RNApp,
  RNOHErrorDialog,
  RNOHLogger,
  TraceJSBundleProviderDecorator,
  RNOHCoreContext
} from '@rnoh/react-native-openharmony';
import { createRNPackages } from '../RNPackagesFactory';
 
// 用于构建自定义 RN 组件的 Builder
@Builder
export function buildCustomRNComponent(ctx: ComponentBuilderContext) {}
 
const wrappedCustomRNComponentBuilder = wrapBuilder(buildCustomRNComponent)
 
@Entry
@Component
struct Index {
  @StorageLink('RNOHCoreContext') private rnohCoreContext: RNOHCoreContext | undefined = undefined
  @State shouldShow: boolean = false
  @State rnInstanceKey: number = 0 // 用于强制重新创建 RNApp 组件
  private logger!: RNOHLogger
 
  aboutToAppear() {
    this.logger = this.rnohCoreContext!.logger.clone("Index")
    const stopTracing = this.logger.clone("aboutToAppear").startTracing();
    this.shouldShow = true
    stopTracing();
  }
 
  // 清理方法
  private cleanUp() {
    this.logger.info("Cleaning up RN instance")
    this.shouldShow = false
  }
 
  // 初始化方法
  private init() {
    this.logger.info("Initializing new RN instance")
    this.rnInstanceKey += 1 // 改变 key 强制重新渲染 RNApp
    this.shouldShow = true
  }
 
  onBackPress(): boolean | undefined {
    // 拦截物理返回键,交给 React Native 处理
    this.rnohCoreContext!.dispatchBackPress()
    return true
  }
 
  build() {
    Column() {
      if (this.rnohCoreContext && this.shouldShow) {
        if (this.rnohCoreContext?.isDebugModeEnabled) {
          RNOHErrorDialog({ ctx: this.rnohCoreContext })
        }
        RNApp({
          rnInstanceConfig: {
            createRNPackages,
            enableNDKTextMeasuring: true,
            enableBackgroundExecutor: false,
            enableCAPIArchitecture: true,
            arkTsComponentNames: []
          },
          initialProps: { "foo": "bar" } as Record<string, string>,
          appKey: "AwesomeProject",
          wrappedCustomRNComponentBuilder: wrappedCustomRNComponentBuilder,
          onSetUp: (rnInstance) => {
            rnInstance.enableFeatureFlag("ENABLE_RN_INSTANCE_CLEAN_UP");
 
            this.rnohCoreContext?.devToolsController?.eventEmitter.subscribe("RELOAD", async () => {
              this.logger.info("Hot reload triggered via RELOAD event");
              this.cleanUp();
              setTimeout(() => {
                this.init();
              }, 100);
            });
          },
 
          jsBundleProvider: new TraceJSBundleProviderDecorator(
            new AnyJSBundleProvider([
              new MetroJSBundleProvider(),
              new FileJSBundleProvider('/data/storage/el2/base/files/bundle.harmony.js'),
              new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'hermes_bundle.hbc'),
              new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'bundle.harmony.js')
            ]),
            this.rnohCoreContext.logger),
        })
 
      }
    }
    .height('100%')
    .width('100%')
  }
}

2.3搭建热更新

先运行自己的鸿蒙项目,当模拟器启动成功后,在终端执行'hdc rport tcp:8081 tcp:8081"的命令。(注意:必须完成这一步出现“Ok”,不然后续步骤无法实现。)。在项目的根目录,也就是(React/AwesomeProject)执行"npm run start"的命令,会出现让你选r、d、i、a的选项。我们在终端输入r即可。然后就可以改了。我们改动首页的内容"不是对你没感觉,只因你没开保时捷"和"三年舔狗一场空,租车一夜喊老公",可以看到我们几乎几秒就更新上去啦!

r、d、i、a的选项解释:

r - reload the app
d - open developer menu
i - run on iOS
a - run on Android

先打开手机模拟器运行自己的鸿蒙项目

在模拟器终端执行"hdc rport tcp:8081 tcp:8081"的命令

在AwesomeProject文件夹终端执行"npm run start"的命令,会出现让你选r、d、i、a的选项。我们在终端输入r即可。然后就可以改了

上面运行成功后就可以进入到AwesomeProject\src\screens\HomeScreen.tsx

启动完手机模拟器之后,修改下面红色框内的两行内容,模拟器上的内容也会随之同步

项目运行成功

到此,文章完结,如果有疑问,可以在评论区留言。如果我的文章对你有帮助,请点赞支持一下,非常感谢

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐