说明

这是一个使用 FrameNode 进行 bundle 预加载的 demo 工程。

目录结构

GenerateBundle – RN 侧工程
FrameNodeSampleApp – 原生工程

环境搭建

  1. GenerateBundle 目录下执行 npm i @react-native-oh/react-native-harmony@x.x.xyarn add @react-native-oh/react-native-harmony@x.x.x 安装依赖,执行 npm run dev 生成 bundle;
  2. entry 目录下执行 ohpm i @rnoh/react-native-openharmony@x.x.x 安装依赖;
  3. 检查 FrameNodeSampleAppentry 目录下是否生成 oh-modules 文件夹;
  4. 用 DevEco Studio 打开 FrameNodeSampleApp,执行 Sync and Refresh Project
  5. 点击 File > Project Structure > Signing Configs,登录并完成签名;
  6. 点击右上角的 run 启动项目。

效果预览

在成功运行demo工程之后,打开应用如下图所示:

请添加图片描述

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 */

import React, { useState } from 'react';
import { View, Text, FlatList, TouchableOpacity, StyleSheet } from 'react-native';

const App = () => {
  // 左侧列表的数据
  const categories = ['Category 1', 'Category 2', 'Category 3', 'Category 4'];

  // 右侧列表的数据 (基于左侧选中的分类)
  const data = {
    'Category 1': ['Item 1-1', 'Item 1-2', 'Item 1-3'],
    'Category 2': ['Item 2-1', 'Item 2-2'],
    'Category 3': ['Item 3-1', 'Item 3-2', 'Item 3-3', 'Item 3-4'],
    'Category 4': ['Item 4-1', 'Item 4-2', 'Item 4-3']
  };

  // 当前选中的分类
  const [selectedCategory, setSelectedCategory] = useState(categories[0]);

  return (
    <View style={styles.container}>
      {/* 左侧列表 */}
      <FlatList
        style={styles.leftList}
        data={categories}
        keyExtractor={(item) => item}
        renderItem={({ item }) => (
          <TouchableOpacity
            onPress={() => setSelectedCategory(item)}
            style={[
              styles.item,
              selectedCategory === item && styles.selectedItem
            ]}
          >
            <Text style={styles.itemText}>{item}</Text>
          </TouchableOpacity>
        )}
      />

      {/* 右侧列表 */}
      <FlatList
        style={styles.rightList}
        data={data[selectedCategory]}
        keyExtractor={(item) => item}
        renderItem={({ item }) => (
          <View style={styles.item}>
            <Text style={styles.itemText}>{item}</Text>
          </View>
        )}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    padding: 10
  },
  leftList: {
    width: '40%',
    marginRight: 10
  },
  rightList: {
    width: '60%'
  },
  item: {
    padding: 20,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc'
  },
  selectedItem: {
    backgroundColor: '#dcdcdc'
  },
  itemText: {
    fontSize: 16
  }
});

export default App;

这是一个完整的 React Native 应用程序代码,实现了一个典型的双列表交互界面,类似于电商应用中常见的分类-商品列表布局。该应用展示了 React Native 框架在现代移动应用开发中的核心优势和实践模式。

从整体架构来看,这个应用采用了标准的 React 函数式组件开发模式,充分利用了 Hooks 特性来管理组件状态。代码结构清晰,分为数据定义、组件逻辑、样式定义三个主要部分,体现了关注点分离的设计原则。

在数据层设计上,应用定义了两个核心数据结构。categories 数组包含了四个分类项,作为左侧列表的数据源。data 对象则是一个映射结构,将每个分类与对应的项目数组关联起来,这种设计模式在实际业务场景中非常实用,能够有效地组织和管理层次化数据。

组件内部使用 useState Hook 来管理当前选中的分类状态,初始值设置为 categories 数组的第一个元素。这种状态管理方式确保了 UI 与数据的同步更新,当用户选择不同的分类时,右侧列表能够实时响应用户交互并显示对应的内容。

界面布局采用了经典的左右分栏设计,通过 View 组件的 flexDirection: ‘row’ 属性实现水平排列。左侧列表占据 40% 的宽度,右侧列表占据 60% 的宽度,这种比例分配既保证了导航的清晰可见,又为内容展示提供了充足空间。两个列表之间设置了 10 像素的间距,避免了视觉上的拥挤感。

左侧列表使用 FlatList 组件实现,这是一个高性能的滚动列表组件,专门用于渲染长列表数据。每个列表项都被包装在 TouchableOpacity 组件中,提供了良好的触摸反馈效果。当用户点击某个分类时,通过 onPress 事件处理器调用 setSelectedCategory 来更新选中状态。

在样式处理上,左侧列表项采用了条件渲染的方式,根据当前选中的分类动态应用不同的样式。选中的项通过 selectedItem 样式类显示为浅灰色背景,这种视觉反馈帮助用户明确当前所处的导航位置。

右侧列表同样使用 FlatList 组件,但其数据源依赖于 selectedCategory 状态。通过 data[selectedCategory] 这种动态数据访问模式,实现了两个列表之间的数据联动。这种设计模式在需要展示层次化数据的应用中非常常见。

样式系统通过 StyleSheet.create 方法定义,这是一种性能优化的做法,可以避免不必要的样式对象重复创建。容器样式设置了 flex: 1 使其充满整个屏幕,同时定义了水平排列方式和内边距。列表项样式统一设置了内边距、底部边框和边框颜色,创建了清晰的视觉分隔。

左侧列表设置了固定的宽度百分比和右边距,右侧列表则占据剩余空间。这种响应式布局设计确保了在不同尺寸的移动设备上都能保持良好的视觉效果。

从用户体验的角度分析,这个应用实现了几个重要的交互特性:直观的导航系统、即时的内容更新、清晰的视觉反馈、流畅的滚动体验。这些特性共同构成了一个高质量移动应用的基础。

在性能优化方面,使用 FlatList 而非 ScrollView 来渲染列表是一个关键决策。FlatList 采用了懒加载机制,只渲染当前可见区域的列表项,这对于包含大量数据的列表来说至关重要。

代码的可维护性也值得关注。常量和样式都被提取到组件外部,使得主要逻辑更加清晰。keyExtractor 函数的定义确保了每个列表项都有稳定的唯一标识,这是 React 列表渲染的最佳实践。

从 React Native 开发模式的角度来看,这个示例展示了声明式 UI 编程的核心优势。开发者只需要描述 UI 应该呈现的状态,而不需要关心如何从一种状态过渡到另一种状态,这种抽象大大降低了开发复杂度。

样式定义部分体现了 React Native 样式系统的特点。虽然语法类似于 CSS,但采用的是 JavaScript 对象的形式,并且只支持 Flexbox 布局模型。这种设计选择虽然限制了某些传统 CSS 特性的使用,但带来了更好的性能和一致性。

导出部分使用 export default App 确保了这个组件可以被其他模块正确导入。在典型的 React Native 项目中,这个组件会被注册为应用的根组件。

从业务应用场景来看,这种双列表布局模式可以适用于多种类型的应用:电商平台的分类浏览、内容管理系统的目录导航、设置界面的分组选项等。其灵活性和实用性使得它成为移动应用设计中一个经典的模式。

在更深层次的技术实现上,这个应用涉及到了 React Native 架构的多个重要方面:JS 线程与原生线程的通信、Shadow Tree 的构建、原生视图的更新等。虽然这些底层细节在代码中没有直接体现,但它们对于应用的正常运行至关重要。

错误处理方面,虽然这个示例中没有显式的错误处理代码,但通过 TypeScript 的类型检查和 React 的运行时检查,应用仍然具备一定的健壮性。

从学习价值的角度,这个代码示例涵盖了 React Native 开发的多个核心概念:组件定义、状态管理、事件处理、列表渲染、样式应用等。对于初学者来说,理解这个组件的各个部分是如何协同工作的,是掌握更复杂应用开发的基础。

代码的注释和格式也体现了良好的编程习惯。文件头部的注释说明了代码的来源和用途,导入语句组织有序,代码块之间的空行提高了可读性。

在可访问性方面,虽然这个示例没有显式设置 accessibility 属性,但 TouchableOpacity 组件本身就提供了基本的可访问性支持。

从现代移动应用开发趋势来看,这个应用体现了几个重要方向:组件化架构、声明式编程、跨平台开发、性能优先设计等。

总之,这个 React Native 应用虽然功能相对简单,但完整地展示了现代移动应用开发的核心技术和最佳实践。它不仅仅是一个可以运行的代码示例,更是一个包含了丰富设计理念和工程智慧的完整解决方案。通过深入分析这个示例,开发者可以获得对 React Native 框架和移动应用开发的深刻理解。


RN 分列列表bundle预加载
操作:点击首页中间的按钮,跳转到新页面中,框内加载出RN bundle中的分列列表。
效果:如下图所示
请添加图片描述

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐