在现代电商应用中,个性化推荐已成为提升用户体验和转化率的关键技术。本文将深入分析一个基于 React Native 实现的智能推荐浏览系统,探讨其架构设计、技术实现以及鸿蒙跨端适配策略。

数据模型

该系统构建了两个核心数据模型,为智能推荐提供了完整的数据支持:

// 商品类型
type Product = {
  id: string;
  name: string;
  price: number;
  // 其他属性...
  recommendationReason: string;
};

// 分类类型
type Category = {
  id: string;
  name: string;
  icon: string;
};

这种数据模型设计的优势:

  • 完整性:涵盖了商品的核心属性,包括推荐理由
  • 关联性:通过推荐理由建立商品与用户之间的关联
  • 扩展性:类型定义清晰,便于后续功能扩展
  • 类型安全:使用 TypeScript 类型确保数据结构一致性

状态管理

系统采用了 React Hooks 中的 useState 进行轻量级状态管理:

const [products] = useState<Product[]>([
  // 商品数据...
]);

const [categories] = useState<Category[]>([
  // 分类数据...
]);

const [recommendedForYou] = useState<Product[]>([
  products[0],
  products[3],
  products[6],
  products[1],
]);

const [trendingProducts] = useState<Product[]>([
  products[2],
  products[4],
  products[5],
  products[7],
]);

这种状态管理方式具有以下优势:

  • 模块化:将不同类型的数据分离管理
  • 响应式:状态变更自动触发组件重渲染
  • 跨端兼容:React Hooks 在鸿蒙系统的 React Native 实现中通常都有良好支持
  • 数据分层:将商品数据分为全部商品、为你推荐和热门商品三个层次

基础架构

该实现采用了 React Native 核心组件库,确保了在鸿蒙系统上的基本兼容性:

  • SafeAreaView:适配刘海屏等异形屏
  • ScrollView:处理内容滚动
  • TouchableOpacity:提供触摸反馈
  • FlatList:高效渲染商品列表
  • Image:显示商品图片
  • Alert:系统级弹窗提示

Base64 图标

系统使用 Base64 编码的图标库:

const ICONS_BASE64 = {
  home: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  // 其他图标...
};

这种处理方式在跨端开发中尤为重要:

  • 避免了不同平台对资源文件格式的兼容性问题
  • 减少了网络请求,提高了加载速度
  • 简化了构建流程,无需处理多平台资源文件

屏幕尺寸

系统通过 Dimensions API 获取屏幕尺寸:

const { width, height } = Dimensions.get('window');

这种方式确保了在不同屏幕尺寸的设备上都能获得一致的布局体验,无论是 React Native 环境还是鸿蒙系统。


系统采用了模块化的样式定义:

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f5f5',
  },
  // 其他样式...
});

这种方式确保了样式的一致性和可维护性,同时为后续的主题定制和深色模式适配预留了扩展空间。


在鸿蒙系统上使用 React Native 时,应注意以下 API 兼容性问题:

  1. FlatList API:鸿蒙系统的 FlatList 实现可能与 React Native 有所差异,建议测试确认滚动和渲染行为
  2. Image API:鸿蒙系统的 Image 实现可能与 React Native 有所差异,建议测试确认图片加载行为
  3. TouchableOpacity API:鸿蒙系统的 TouchableOpacity 实现可能与 React Native 有所差异,建议测试确认触摸反馈

  1. 类型定义

    // 更详细的商品类型
    interface Product {
      id: string;
      name: string;
      price: number;
      originalPrice?: number;
      rating: number;
      reviewCount: number;
      store: string;
      category: string;
      imageUrl?: string;
      isFavorite: boolean;
      discount?: number;
      tags?: string[];
      recommendationReason: string;
      stock?: number;
      sales?: number;
      relevanceScore?: number; // 推荐相关度分数
    }
    
    // 更详细的分类类型
    interface Category {
      id: string;
      name: string;
      icon: string;
      count?: number;
      subcategories?: SubCategory[];
    }
    
  2. 状态管理

    // 使用 useReducer 管理复杂状态
    const [state, dispatch] = useReducer(appReducer, {
      products: initialProducts,
      categories: initialCategories,
      recommendedForYou: initialRecommendedForYou,
      trendingProducts: initialTrendingProducts,
      loading: false,
      error: null
    });
    
  3. 性能

    // 使用 useMemo 缓存计算结果
    const personalizedRecommendations = useMemo(() => {
      return products.filter(product => product.relevanceScore && product.relevanceScore > 0.5);
    }, [products]);
    
    // 列表渲染优化
    <FlatList
      data={recommendedForYou}
      keyExtractor={item => item.id}
      renderItem={renderProduct}
      numColumns={2}
      showsVerticalScrollIndicator={false}
      initialNumToRender={4}
      maxToRenderPerBatch={4}
      windowSize={5}
    />
    
  4. 错误处理

    // 添加错误边界
    const addToCart = (productId: string) => {
      try {
        // 加入购物车逻辑
        Alert.alert('加入购物车', `已将商品加入购物车`);
      } catch (error) {
        console.error('加入购物车失败:', error);
        Alert.alert('错误', '加入购物车失败,请稍后重试');
      }
    };
    
  5. 可访问性

    // 添加可访问性标签
    <TouchableOpacity
      accessible={true}
      accessibilityLabel={`查看商品: ${item.name}`}
      // 其他属性
    />
    

本智能推荐系统实现了一个功能完整、用户友好的个性化推荐界面,通过合理的架构设计和代码组织,为用户提供了良好的购物体验。在跨端开发场景下,该实现充分考虑了 React Native 和鸿蒙系统的兼容性需求,为后续的功能扩展和性能优化预留了空间。


智能推荐已成为电商产品提升用户体验和转化效率的核心能力,其前端实现需要兼顾个性化数据展示、多维度内容布局、流畅的交互体验三大核心诉求。本文将深度拆解这份基于 React Native 构建的智能推荐电商应用代码,从数据模型设计、页面架构分层、交互逻辑实现、视觉样式体系四个维度剖析其技术内核,并提供完整的鸿蒙(HarmonyOS)ArkTS 跨端适配方案,为跨端智能推荐类电商应用开发提供可落地的技术参考。

1. 数据模型

智能推荐电商应用的核心是商品数据 + 推荐逻辑的深度融合,代码通过 TypeScript 构建了两层数据模型体系,精准匹配个性化推荐场景的业务需求:

(1)核心数据
// 商品核心类型:新增推荐原因字段,适配智能推荐场景
type Product = {
  id: string;
  name: string;
  price: number;
  originalPrice?: number;
  rating: number;
  reviewCount: number;
  store: string;
  category: string;
  imageUrl?: string;
  isFavorite: boolean;
  discount?: number;
  tags?: string[];
  recommendationReason: string; // 推荐原因:智能推荐核心字段
};

// 分类类型:适配商品分类导航场景
type Category = {
  id: string;
  name: string;
  icon: string;
};

设计亮点分析:

  • 场景化扩展:在基础商品模型上新增 recommendationReason 字段,直接承载智能推荐的核心逻辑,将推荐理由可视化呈现给用户;
  • 分类模型轻量化:分类类型仅保留核心的 ID、名称、图标字段,符合移动端分类导航的轻量化展示需求;
  • 可选属性合理设计originalPrice/discount/tags 等字段采用可选类型,适配不同商品的差异化展示需求;
  • 类型安全保障:通过 TypeScript 类型定义,避免运行时数据类型错误,提升代码健壮性。
(2)状态管理
// 核心数据状态:商品列表/分类列表/推荐商品分组
const [products] = useState<Product[]>([/* 完整商品列表 */]);
const [categories] = useState<Category[]>([/* 分类列表 */]);
const [recommendedForYou] = useState<Product[]>([/* 为您推荐商品 */]);
const [trendingProducts] = useState<Product[]>([/* 热门推荐商品 */]);

状态设计遵循数据分层管理原则:

  • 基础数据层:productscategories 存储全量商品和分类数据,作为整个应用的数据基础;
  • 推荐分组层:recommendedForYoutrendingProducts 基于全量商品数据进行分组,适配不同推荐场景的展示需求;
  • 不可变状态设计:使用 useState 初始化后不再变更(实际项目中可对接推荐 API 动态更新),符合 React 函数式组件的状态设计理念。

2. 交互逻辑

智能推荐电商应用的核心价值在于个性化展示-用户转化的闭环,代码实现了完整的交互逻辑体系,覆盖商品操作、分类导航、个性化设置等核心场景:

(1)商品核心
// 商品收藏切换:状态反馈型交互
const toggleFavorite = (productId: string) => {
  Alert.alert('收藏', `商品已${products.find(p => p.id === productId)?.isFavorite ? '取消收藏' : '收藏'}`);
};

// 加入购物车:操作反馈型交互
const addToCart = (productId: string) => {
  Alert.alert('加入购物车', `已将商品加入购物车`);
};

// 查看商品详情:导航型交互
const viewProduct = (productId: string) => {
  Alert.alert('商品详情', `查看商品: ${products.find(p => p.id === productId)?.name}`);
};

设计亮点:

  • 参数化设计:所有操作函数均接收 productId 作为参数,实现精准的商品定位,符合面向数据的编程思想;
  • 反馈明确化:每个操作均通过 Alert.alert 给出即时反馈,提升用户操作感知;
  • 数据关联查询:通过 find 方法根据 ID 匹配商品数据,实现操作与数据的精准关联;
  • 逻辑解耦:核心操作封装为独立函数,便于后续对接后端 API、添加加载状态、埋点统计等扩展逻辑。
(2)列表渲染

代码实现了三种核心列表的渲染函数,采用组件化设计思想,保证渲染逻辑的复用性和可维护性:

商品卡片
const renderProduct = ({ item }: { item: Product }) => (
  <TouchableOpacity style={styles.productCard} onPress={() => viewProduct(item.id)}>
    {/* 商品卡片完整内容:图片占位 + 名称 + 价格体系 + 评分 + 店铺 + 标签 + 推荐理由 + 操作按钮 */}
  </TouchableOpacity>
);
分类卡片
const renderCategory = ({ item }: { item: Category }) => (
  <TouchableOpacity 
    style={styles.categoryCard}
    onPress={() => Alert.alert('分类', `查看${item.name}商品`)}
  >
    {/* 分类卡片内容:图标 + 名称 */}
  </TouchableOpacity>
);

设计亮点:

  • 组件化封装:每个列表项封装为独立渲染函数,可在不同推荐模块中复用;
  • 交互绑定差异化:商品卡片绑定详情查看操作,分类卡片绑定分类筛选操作,符合不同模块的交互逻辑;
  • 内容适配性:商品卡片包含推荐理由字段,突出智能推荐的核心特性;
  • 视觉层次化:通过样式区分不同信息层级,重点突出价格、名称等核心转化要素。

应用采用头部导航 + 搜索栏 + 分类导航 + 多模块推荐内容 + 底部导航的经典电商布局,结合智能推荐的业务特性,打造了符合用户浏览习惯的个性化体验。

(1)整体布局
SafeAreaView
├── Header(头部:标题 + 搜索/购物车按钮)
├── ScrollView(滚动内容区)
│   ├── SearchContainer(搜索栏)
│   ├── 分类导航模块(横向滚动分类列表)
│   ├── 为您推荐模块(双列商品列表)
│   ├── 热门推荐模块(双列商品列表)
│   ├── 猜您喜欢模块(横向滚动商品列表)
│   ├── 推荐原理说明模块
│   └── 个性化设置模块
└── BottomNav(底部导航:首页/分类/购物车/我的)

布局设计优势:

  • 内容分层清晰:将推荐内容按“为您推荐-热门推荐-猜您喜欢”进行分组,符合用户对推荐内容的认知习惯;
  • 多维度展示:同时采用双列网格布局(为您推荐/热门推荐)和横向滚动布局(猜您喜欢),适配不同推荐场景的展示需求;
  • 推荐透明化:新增推荐原理说明和个性化设置模块,提升用户对推荐逻辑的信任感;
  • 交互便捷性:搜索栏置顶,分类导航横向滚动,核心操作入口固定在底部,符合移动端电商应用的交互范式;
  • 响应式适配:通过 flex: 0.48 实现商品卡片的双列自适应布局,适配不同屏幕尺寸。

分类导航
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.categoriesContainer}>
  <View style={styles.categoriesList}>
    {categories.map(category => (
      <TouchableOpacity 
        key={category.id} 
        style={styles.categoryCard}
        onPress={() => Alert.alert('分类', `查看${category.name}商品`)}
      >
        <View style={styles.categoryIcon}>
          <Text style={styles.categoryIconText}>{category.icon}</Text>
        </View>
        <Text style={styles.categoryName}>{category.name}</Text>
      </TouchableOpacity>
    ))}
  </View>
</ScrollView>

设计亮点:

  • 横向滚动适配:使用 ScrollView 结合 horizontal 属性实现分类的横向滚动,节省垂直空间;
  • 轻量化展示:分类卡片仅展示图标和名称,视觉简洁,易于快速识别;
  • 交互反馈:点击分类给出明确的操作反馈,为后续分类筛选功能预留扩展空间。
多形态商品
// 双列网格布局(为您推荐/热门推荐)
<FlatList
  data={recommendedForYou}
  renderItem={renderProduct}
  keyExtractor={item => item.id}
  numColumns={2}
  columnWrapperStyle={styles.productRow}
  showsVerticalScrollIndicator={false}
  contentContainerStyle={styles.productList}
/>

// 横向滚动布局(猜您喜欢)
<ScrollView 
  horizontal 
  showsHorizontalScrollIndicator={false} 
  style={styles.horizontalScroll}
  contentContainerStyle={styles.horizontalScrollContent}
>
  {products.map(product => (
    <TouchableOpacity 
      key={product.id} 
      style={styles.horizontalProductCard}
      onPress={() => viewProduct(product.id)}
    >
      {/* 简化版商品卡片 */}
    </TouchableOpacity>
  ))}
</ScrollView>

设计亮点:

  • 布局差异化:核心推荐内容采用双列网格布局,提供完整的商品信息;辅助推荐内容采用横向滚动布局,突出轻量化展示;
  • 信息适配性:横向滚动的商品卡片简化了信息展示,仅保留核心的图片、名称、价格和简短推荐理由,适配横向浏览的视觉习惯;
  • 性能优化:使用 FlatList 替代 ScrollView + map 渲染长列表,利用 FlatList 的复用机制提升渲染性能;
  • 滚动体验优化:关闭滚动指示器(showsVerticalScrollIndicator={false}),提升视觉体验。

// 推荐原理说明
<View style={styles.reasonExplanation}>
  <Text style={styles.reasonTitle}>推荐原理</Text>
  <Text style={styles.reasonText}>• 基于您的浏览历史</Text>
  <Text style={styles.reasonText}>• 考虑您的购买偏好</Text>
  <Text style={styles.reasonText}>• 结合热门趋势数据</Text>
  <Text style={styles.reasonText}>• 匹配您的兴趣标签</Text>
</View>

// 个性化设置
<View style={styles.settingsCard}>
  <Text style={styles.settingsTitle}>个性化设置</Text>
  <TouchableOpacity style={styles.settingsItem}>
    <Text style={styles.settingsItemText}>管理兴趣标签</Text>
    <Text style={styles.arrow}></Text>
  </TouchableOpacity>
  {/* 其他设置项 */}
</View>

设计亮点:

  • 信任构建:通过推荐原理说明,提升用户对推荐系统的信任感和接受度;
  • 用户掌控:提供个性化设置入口,让用户可以管理自己的推荐偏好,符合隐私保护的设计原则;
  • 视觉区分:采用卡片式设计,与商品推荐模块形成视觉区分,提升页面层次感。
(3)样式

代码通过 StyleSheet.create 构建了完整的样式体系,遵循复用性 + 语义化 + 视觉一致性原则,适配智能推荐电商场景的视觉需求:

  • 色彩体系:主色调采用蓝色(#3b82f6),警示色/价格色采用红色(#ef4444),辅助色采用橙色(#f59e0b),中性色采用灰度渐变,符合电商视觉设计规范;
  • 卡片设计体系:所有核心模块均采用卡片式设计(borderRadius: 12),通过阴影(shadow/elevation)提升视觉层次感;
  • 间距规范:采用 16px/12px/8px/4px 的间距体系,保证页面布局的呼吸感和一致性;
  • 文字层级:通过字体大小(18px/16px/14px/12px/10px)和字重区分信息重要程度,推荐理由等辅助信息采用斜体和浅灰色,突出核心信息;
  • 响应式尺寸:商品卡片使用 flex: 0.48 实现自适应双列布局,横向商品卡片使用固定宽度(120px)保证展示一致性。

将 React Native 智能推荐电商应用迁移至鸿蒙平台,核心是基于 ArkTS + ArkUI 实现数据模型、状态管理、布局架构、交互逻辑的对等还原,同时适配鸿蒙的组件特性和布局方式,以下是完整的适配方案:

1. 状态管理

RN 的 TypeScript 类型体系可无缝迁移至鸿蒙 ArkTS,仅需调整类型定义语法,核心字段和业务逻辑完全复用:

(1)数据类型
// 鸿蒙 ArkTS 类型定义
interface Product {
  id: string;
  name: string;
  price: number;
  originalPrice?: number;
  rating: number;
  reviewCount: number;
  store: string;
  category: string;
  imageUrl?: string;
  isFavorite: boolean;
  discount?: number;
  tags?: string[];
  recommendationReason: string;
}

interface Category {
  id: string;
  name: string;
  icon: string;
}
(2)状态管理
@Entry
@Component
struct RecommendApp {
  // 核心数据状态:完全复用 RN 的数据初始化逻辑
  @State products: Product[] = [
    { id: '1', name: 'iPhone 15 Pro Max', price: 9999, originalPrice: 10999, rating: 4.8, reviewCount: 1250, store: '苹果官方旗舰店', category: '手机', isFavorite: false, discount: 10, tags: ['热销', '正品'], recommendationReason: '根据您的浏览历史推荐' },
    // 其他商品数据...
  ];
  
  @State categories: Category[] = [
    { id: 'c1', name: '手机数码', icon: '📱' },
    // 其他分类数据...
  ];
  
  @State recommendedForYou: Product[] = [
    this.products[0],
    this.products[3],
    this.products[6],
    this.products[1],
  ];
  
  @State trendingProducts: Product[] = [
    this.products[2],
    this.products[4],
    this.products[5],
    this.products[7],
  ];
  
  // 核心操作逻辑:仅需适配弹窗 API,业务逻辑完全复用
  toggleFavorite(productId: string) {
    AlertDialog.show({
      title: '收藏',
      message: `商品已${this.products.find(p => p.id === productId)?.isFavorite ? '取消收藏' : '收藏'}`,
      confirm: { value: '确定' }
    });
  }
  
  addToCart(productId: string) {
    AlertDialog.show({
      title: '加入购物车',
      message: `已将商品加入购物车`,
      confirm: { value: '确定' }
    });
  }
  
  viewProduct(productId: string) {
    AlertDialog.show({
      title: '商品详情',
      message: `查看商品: ${this.products.find(p => p.id === productId)?.name}`,
      confirm: { value: '确定' }
    });
  }
  
  // 商品卡片构建函数:替代 RN 的 renderProduct 函数
  @Builder
  renderProduct(item: Product) {
    Column()
      .backgroundColor('#ffffff')
      .borderRadius(12)
      .padding(12)
      .flexGrow(0)
      .flexShrink(0)
      .width('48%')
      .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 })
      .onClick(() => this.viewProduct(item.id)) {
      
      // 商品图片占位
      Column()
        .width('100%')
        .height(100)
        .borderRadius(8)
        .backgroundColor('#f1f5f9')
        .justifyContent(FlexAlign.Center)
        .alignItems(ItemAlign.Center)
        .marginBottom(8) {
        Text('📱')
          .fontSize(30);
      }
      
      // 商品名称
      Text(item.name)
        .fontSize(14)
        .fontWeight(FontWeight.Medium)
        .fontColor('#1e293b')
        .marginBottom(8)
        .maxLines(2);
      
      // 价格区域
      Row()
        .alignItems(ItemAlign.Center)
        .marginBottom(4) {
        Text(`¥${item.price}`)
          .fontSize(16)
          .fontColor('#ef4444')
          .fontWeight(FontWeight.Bold)
          .marginRight(8);
        
        if (item.originalPrice) {
          Text(`¥${item.originalPrice}`)
            .fontSize(12)
            .fontColor('#94a3b8')
            .decoration({ type: TextDecorationType.LineThrough })
            .marginRight(8);
        }
        
        if (item.discount) {
          Text(`-${item.discount}%`)
            .fontSize(10)
            .fontColor('#ffffff')
            .backgroundColor('#ef4444')
            .padding({ left: 4, right: 4, top: 2, bottom: 2 })
            .borderRadius(4);
        }
      }
      
      // 评分区域
      Row()
        .alignItems(ItemAlign.Center)
        .marginBottom(4) {
        Text(`${item.rating}`)
          .fontSize(12)
          .fontColor('#f59e0b')
          .marginRight(8);
        Text(`(${item.reviewCount})`)
          .fontSize(12)
          .fontColor('#64748b');
      }
      
      // 店铺名称
      Text(item.store)
        .fontSize(12)
        .fontColor('#64748b')
        .marginBottom(8);
      
      // 标签区域
      Row()
        .flexWrap(FlexWrap.Wrap)
        .marginBottom(8) {
        if (item.tags) {
          item.tags.forEach(tag => {
            Column()
              .backgroundColor('#dbeafe')
              .padding({ left: 6, right: 6, top: 2, bottom: 2 })
              .borderRadius(4)
              .marginRight(4)
              .marginBottom(4) {
              Text(tag)
                .fontSize(10)
                .fontColor('#3b82f6');
            }
          });
        }
      }
      
      // 推荐理由
      Text(item.recommendationReason)
        .fontSize(10)
        .fontColor('#94a3b8')
        .fontStyle(FontStyle.Italic)
        .marginBottom(8);
      
      // 操作按钮
      Row()
        .justifyContent(FlexAlign.SpaceBetween)
        .marginTop(8) {
        Button()
          .padding(8)
          .backgroundColor(Color.Transparent)
          .onClick(() => this.toggleFavorite(item.id)) {
            Text(item.isFavorite ? '❤️' : '🤍')
              .fontSize(20);
          }
        
        Button()
          .backgroundColor('#3b82f6')
          .padding({ top: 8, bottom: 8, left: 16, right: 16 })
          .borderRadius(6)
          .onClick(() => this.addToCart(item.id)) {
            Text('🛒')
              .fontSize(16)
              .fontColor('#ffffff');
          }
      }
    }
  }
  
  // 分类卡片构建函数
  @Builder
  renderCategory(item: Category) {
    Column()
      .backgroundColor('#ffffff')
      .borderRadius(12)
      .padding(16)
      .marginRight(12)
      .alignItems(ItemAlign.Center)
      .width(70)
      .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 })
      .onClick(() => {
        AlertDialog.show({
          title: '分类',
          message: `查看${item.name}商品`,
          confirm: { value: '确定' }
        });
      }) {
      
      Column()
        .width(32)
        .height(32)
        .borderRadius(16)
        .backgroundColor('#dbeafe')
        .justifyContent(FlexAlign.Center)
        .alignItems(ItemAlign.Center)
        .marginBottom(8) {
        Text(item.icon)
          .fontSize(16)
          .fontColor('#3b82f6');
      }
      
      Text(item.name)
        .fontSize(12)
        .fontColor('#1e293b')
        .textAlign(TextAlign.Center);
    }
  }
  
  // 横向商品卡片构建函数
  @Builder
  renderHorizontalProduct(item: Product) {
    Column()
      .backgroundColor('#ffffff')
      .borderRadius(12)
      .padding(12)
      .width(120)
      .marginRight(12)
      .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 })
      .onClick(() => this.viewProduct(item.id)) {
      
      Column()
        .width('100%')
        .height(80)
        .borderRadius(8)
        .backgroundColor('#f1f5f9')
        .justifyContent(FlexAlign.Center)
        .alignItems(ItemAlign.Center)
        .marginBottom(8) {
        Text('📱')
          .fontSize(30);
      }
      
      Text(item.name)
        .fontSize(12)
        .fontWeight(FontWeight.Medium)
        .fontColor('#1e293b')
        .marginBottom(4)
        .maxLines(1);
      
      Text(`¥${item.price}`)
        .fontSize(14)
        .fontColor('#ef4444')
        .fontWeight(FontWeight.Bold)
        .marginBottom(4);
      
      Text(`${item.recommendationReason.substring(0, 15)}...`)
        .fontSize(10)
        .fontColor('#94a3b8')
        .fontStyle(FontStyle.Italic);
    }
  }
  
  // 页面主构建函数
  build() {
    Column()
      .flex(1)
      .backgroundColor('#f5f7fa')
      .safeArea(true) {
      
      // 头部导航
      this.renderHeader();
      
      // 滚动内容区
      Scroll()
        .flex(1) {
        Column() {
          // 搜索栏
          this.renderSearchBar();
          
          // 分类导航
          this.renderCategoryNav();
          
          // 为您推荐
          this.renderRecommendedForYou();
          
          // 热门推荐
          this.renderTrendingProducts();
          
          // 猜您喜欢
          this.renderYouMayLike();
          
          // 推荐原理
          this.renderReasonExplanation();
          
          // 个性化设置
          this.renderSettings();
        }
      }
      
      // 底部导航
      this.renderBottomNav();
    }
  }
  
  // 头部导航构建函数
  @Builder
  renderHeader() {
    Row()
      .alignItems(ItemAlign.Center)
      .justifyContent(FlexAlign.SpaceBetween)
      .padding(16)
      .backgroundColor('#ffffff')
      .borderBottom({ width: 1, color: '#e2e8f0' }) {
      
      Text('智能推荐')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .fontColor('#1e293b');
      
      Row()
        .alignItems(ItemAlign.Center) {
        // 搜索按钮
        Button()
          .width(36)
          .height(36)
          .borderRadius(18)
          .backgroundColor('#f1f5f9')
          .marginRight(12) {
          Text('🔍')
            .fontSize(18)
            .fontColor('#64748b');
        }
        
        // 购物车按钮(带角标)
        Stack() {
          Button()
            .width(36)
            .height(36)
            .borderRadius(18)
            .backgroundColor('#f1f5f9') {
            Text('🛒')
              .fontSize(18)
              .fontColor('#64748b');
          }
          
          Column()
            .position(Position.Absolute)
            .top(-4)
            .right(-4)
            .backgroundColor('#ef4444')
            .borderRadius(8)
            .minWidth(16)
            .height(16)
            .justifyContent(FlexAlign.Center)
            .alignItems(ItemAlign.Center) {
            Text('3')
              .fontColor('#ffffff')
              .fontSize(10)
              .fontWeight(FontWeight.Bold);
          }
        }
      }
    }
  }
  
  // 搜索栏构建函数
  @Builder
  renderSearchBar() {
    Row()
      .alignItems(ItemAlign.Center)
      .backgroundColor('#ffffff')
      .borderRadius(20)
      .padding({ top: 12, bottom: 12, left: 16, right: 16 })
      .margin(16)
      .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 }) {
      
      Text('🔍')
        .fontSize(18)
        .fontColor('#64748b');
      
      Text('搜索您想要的商品')
        .fontSize(14)
        .fontColor('#94a3b8')
        .marginLeft(12)
        .flex(1);
    }
  }
  
  // 分类导航构建函数
  @Builder
  renderCategoryNav() {
    Column() {
      Text('商品分类')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .fontColor('#1e293b')
        .marginLeft(16)
        .marginBottom(4);
      
      Scroll()
        .scrollable(ScrollDirection.Horizontal)
        .scrollBar(BarState.Off)
        .marginBottom(16) {
        Row()
          .paddingLeft(16) {
          this.categories.forEach(category => {
            this.renderCategory(category);
          });
        }
      }
    }
  }
  
  // 为您推荐构建函数
  @Builder
  renderRecommendedForYou() {
    Column() {
      Text('为您推荐')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .fontColor('#1e293b')
        .marginLeft(16)
        .marginBottom(4);
      
      Text('根据您的喜好为您精心挑选')
        .fontSize(12)
        .fontColor('#64748b')
        .marginLeft(16)
        .marginBottom(12);
      
      Column()
        .paddingLeft(16)
        .paddingRight(16) {
        // 双列布局:循环步长为 2
        for (let i = 0; i < this.recommendedForYou.length; i += 2) {
          Row()
            .justifyContent(FlexAlign.SpaceBetween)
            .marginBottom(16) {
            this.renderProduct(this.recommendedForYou[i]);
            if (i + 1 < this.recommendedForYou.length) {
              this.renderProduct(this.recommendedForYou[i + 1]);
            }
          }
        }
      }
    }
  }
  
  // 热门推荐构建函数
  @Builder
  renderTrendingProducts() {
    Column() {
      Text('热门推荐')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .fontColor('#1e293b')
        .marginLeft(16)
        .marginBottom(4);
      
      Text('大家都在买的好物')
        .fontSize(12)
        .fontColor('#64748b')
        .marginLeft(16)
        .marginBottom(12);
      
      Column()
        .paddingLeft(16)
        .paddingRight(16) {
        for (let i = 0; i < this.trendingProducts.length; i += 2) {
          Row()
            .justifyContent(FlexAlign.SpaceBetween)
            .marginBottom(16) {
            this.renderProduct(this.trendingProducts[i]);
            if (i + 1 < this.trendingProducts.length) {
              this.renderProduct(this.trendingProducts[i + 1]);
            }
          }
        }
      }
    }
  }
  
  // 猜您喜欢构建函数
  @Builder
  renderYouMayLike() {
    Column() {
      Text('猜您喜欢')
        .fontSize(18)
        .fontWeight(FontWeight.Bold)
        .fontColor('#1e293b')
        .marginLeft(16)
        .marginBottom(4);
      
      Text('根据您的浏览记录推荐')
        .fontSize(12)
        .fontColor('#64748b')
        .marginLeft(16)
        .marginBottom(12);
      
      Scroll()
        .scrollable(ScrollDirection.Horizontal)
        .scrollBar(BarState.Off)
        .marginBottom(16) {
        Row()
          .paddingLeft(16)
          .paddingRight(16) {
          this.products.forEach(product => {
            this.renderHorizontalProduct(product);
          });
        }
      }
    }
  }
  
  // 推荐原理构建函数
  @Builder
  renderReasonExplanation() {
    Column()
      .backgroundColor('#ffffff')
      .borderRadius(12)
      .padding(16)
      .marginLeft(16)
      .marginRight(16)
      .marginBottom(16)
      .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 }) {
      
      Text('推荐原理')
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .fontColor('#1e293b')
        .marginBottom(12);
      
      Text('• 基于您的浏览历史')
        .fontSize(14)
        .fontColor('#64748b')
        .lineHeight(22)
        .marginBottom(4);
      
      Text('• 考虑您的购买偏好')
        .fontSize(14)
        .fontColor('#64748b')
        .lineHeight(22)
        .marginBottom(4);
      
      Text('• 结合热门趋势数据')
        .fontSize(14)
        .fontColor('#64748b')
        .lineHeight(22)
        .marginBottom(4);
      
      Text('• 匹配您的兴趣标签')
        .fontSize(14)
        .fontColor('#64748b')
        .lineHeight(22);
    }
  }
  
  // 个性化设置构建函数
  @Builder
  renderSettings() {
    Column()
      .backgroundColor('#ffffff')
      .borderRadius(12)
      .padding(16)
      .marginLeft(16)
      .marginRight(16)
      .marginBottom(20)
      .shadow({ color: '#000', offsetX: 0, offsetY: 1, opacity: 0.1, radius: 2 }) {
      
      Text('个性化设置')
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .fontColor('#1e293b')
        .marginBottom(16);
      
      // 管理兴趣标签
      Row()
        .justifyContent(FlexAlign.SpaceBetween)
        .alignItems(ItemAlign.Center)
        .padding({ top: 12, bottom: 12 })
        .borderBottom({ width: 1, color: '#e2e8f0' }) {
        Text('管理兴趣标签')
          .fontSize(14)
          .fontColor('#1e293b');
        Text('›')
          .fontSize(18)
          .fontColor('#94a3b8');
      }
      
      // 调整推荐偏好
      Row()
        .justifyContent(FlexAlign.SpaceBetween)
        .alignItems(ItemAlign.Center)
        .padding({ top: 12, bottom: 12 })
        .borderBottom({ width: 1, color: '#e2e8f0' }) {
        Text('调整推荐偏好')
          .fontSize(14)
          .fontColor('#1e293b');
        Text('›')
          .fontSize(18)
          .fontColor('#94a3b8');
      }
      
      // 清除浏览历史
      Row()
        .justifyContent(FlexAlign.SpaceBetween)
        .alignItems(ItemAlign.Center)
        .padding({ top: 12, bottom: 12 }) {
        Text('清除浏览历史')
          .fontSize(14)
          .fontColor('#1e293b');
        Text('›')
          .fontSize(18)
          .fontColor('#94a3b8');
      }
    }
  }
  
  // 底部导航构建函数
  @Builder
  renderBottomNav() {
    Row()
      .justifyContent(FlexAlign.SpaceAround)
      .backgroundColor('#ffffff')
      .borderTop({ width: 1, color: '#e2e8f0' })
      .paddingVertical(12)
      .position(Position.Fixed)
      .bottom(0)
      .width('100%') {
      
      // 首页(激活状态)
      Column()
        .alignItems(ItemAlign.Center)
        .flex(1)
        .paddingTop(4)
        .borderTop({ width: 2, color: '#3b82f6' }) {
        Text('🏠')
          .fontSize(20)
          .fontColor('#3b82f6')
          .marginBottom(4);
        Text('首页')
          .fontSize(12)
          .fontColor('#3b82f6')
          .fontWeight(FontWeight.Medium);
      }
      
      // 分类
      Column()
        .alignItems(ItemAlign.Center)
        .flex(1) {
        Text('🔍')
          .fontSize(20)
          .fontColor('#94a3b8')
          .marginBottom(4);
        Text('分类')
          .fontSize(12)
          .fontColor('#94a3b8');
      }
      
      // 购物车
      Column()
        .alignItems(ItemAlign.Center)
        .flex(1) {
        Text('🛒')
          .fontSize(20)
          .fontColor('#94a3b8')
          .marginBottom(4);
        Text('购物车')
          .fontSize(12)
          .fontColor('#94a3b8');
      }
      
      // 我的
      Column()
        .alignItems(ItemAlign.Center)
        .flex(1) {
        Text('👤')
          .fontSize(20)
          .fontColor('#94a3b8')
          .marginBottom(4);
        Text('我的')
          .fontSize(12)
          .fontColor('#94a3b8');
      }
    }
  }
}

React Native 特性 鸿蒙 ArkUI 对应实现 适配关键说明
useState @State 装饰器 状态初始化与更新逻辑完全复用,仅调整语法形式
FlatList(双列) Column + Row + 循环 通过步长为 2 的 for 循环实现双列布局,逻辑一致
ScrollView(横向) Scroll(ScrollDirection.Horizontal) 横向滚动通过滚动方向配置实现,API 语义一致
TouchableOpacity onClick 事件 所有可点击组件通过 onClick 绑定事件,替代 RN 的点击组件
Alert.alert AlertDialog.show 弹窗 API 语法差异,核心功能和交互反馈一致
StyleSheet 链式样式 样式属性(颜色、间距、圆角等)完全复用,通过链式调用实现
numColumns={2} Row + for 循环 双列布局通过循环步长控制,视觉效果完全一致
numberOfLines maxLines 属性 文本行数限制属性名称差异,功能一致
TextDecorationLine decoration 属性 文字装饰线属性语法差异,效果一致

  • 数据层完全复用:商品、分类等核心数据模型字段完全一致,仅调整 TypeScript/ArkTS 类型定义语法;
  • 业务逻辑对等实现:收藏、加购、查看详情等核心业务逻辑无需修改,仅需适配平台特有 API;
  • 布局架构镜像还原:保持“头部-搜索-分类-多模块推荐-底部导航”的核心布局结构,保证用户体验一致性;
  • 视觉体验统一:复用相同的色彩体系、间距规范、圆角大小、字体层级,保证两端视觉效果无差异;
  • 交互反馈一致性:点击反馈、弹窗提示、操作确认等交互细节保持一致,降低用户跨端学习成本。

  1. 数据模型是跨端复用的核心:智能推荐场景下的商品模型(含推荐理由字段)和分类模型可完全跨端复用,仅需调整类型定义语法;
  2. 布局架构可镜像还原:RN 的“双列网格+横向滚动”组合布局,可通过鸿蒙的 Scroll + Column + Row 实现对等还原;
  3. 交互逻辑一致性保障:核心操作(收藏、加购、详情)的业务逻辑完全复用,仅需适配平台特有 API;
  4. 推荐场景差异化适配:推荐原理说明、个性化设置等模块的展示逻辑可完全复用,仅需调整组件语法;
  5. 性能优化按需调整:RN 依赖 FlatList 复用优化,鸿蒙依赖 LazyForEach 懒加载,优化策略虽有差异但目标一致。

React Native 智能推荐电商应用的跨端适配实践,验证了 ArkTS 与 React 技术体系在电商场景下的高度兼容性。对于智能推荐这类以数据展示和个性化交互为核心的场景,90% 以上的业务逻辑和数据模型均可实现跨端复用,仅需适配平台特有 API 和布局语法,是跨端电商应用开发的高效路径。


真实演示案例代码:




// App.tsx
import React, { useState } from 'react';
import { SafeAreaView, View, Text, StyleSheet, TouchableOpacity, ScrollView, Dimensions, Alert, FlatList, Image } from 'react-native';

// Base64 图标库
const ICONS_BASE64 = {
  home: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  recommend: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  cart: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  search: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  favorite: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  trending: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  category: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
  user: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==',
};

const { width, height } = Dimensions.get('window');

// 商品类型
type Product = {
  id: string;
  name: string;
  price: number;
  originalPrice?: number;
  rating: number;
  reviewCount: number;
  store: string;
  category: string;
  imageUrl?: string;
  isFavorite: boolean;
  discount?: number;
  tags?: string[];
  recommendationReason: string;
};

// 分类类型
type Category = {
  id: string;
  name: string;
  icon: string;
};

// 智能推荐浏览应用组件
const RecommendApp: React.FC = () => {
  const [products] = useState<Product[]>([
    { id: '1', name: 'iPhone 15 Pro Max', price: 9999, originalPrice: 10999, rating: 4.8, reviewCount: 1250, store: '苹果官方旗舰店', category: '手机', isFavorite: false, discount: 10, tags: ['热销', '正品'], recommendationReason: '根据您的浏览历史推荐' },
    { id: '2', name: '小米13 Ultra', price: 5999, originalPrice: 6499, rating: 4.7, reviewCount: 890, store: '小米官方旗舰店', category: '手机', isFavorite: true, discount: 8, tags: ['新品', '优惠'], recommendationReason: '同类商品中评分最高' },
    { id: '3', name: '戴尔XPS 13', price: 8999, originalPrice: 9999, rating: 4.6, reviewCount: 560, store: '戴尔官方店', category: '电脑', isFavorite: false, discount: 10, tags: ['热销'], recommendationReason: '您最近搜索过类似商品' },
    { id: '4', name: '索尼WH-1000XM5', price: 2499, originalPrice: 2999, rating: 4.9, reviewCount: 2100, store: '索尼专卖店', category: '耳机', isFavorite: false, discount: 17, tags: ['热销', '推荐'], recommendationReason: '与您购买过的商品相关' },
    { id: '5', name: '美的变频空调', price: 3299, originalPrice: 3999, rating: 4.5, reviewCount: 780, store: '美的官方旗舰店', category: '家电', isFavorite: true, discount: 18, tags: ['爆款'], recommendationReason: '根据季节推荐' },
    { id: '6', name: '耐克运动鞋', price: 799, originalPrice: 899, rating: 4.4, reviewCount: 3200, store: 'Nike官方店', category: '服饰', isFavorite: false, discount: 11, tags: ['热销', '时尚'], recommendationReason: '根据您的兴趣推荐' },
    { id: '7', name: 'iPad Air', price: 4599, originalPrice: 4999, rating: 4.7, reviewCount: 920, store: '苹果官方旗舰店', category: '平板', isFavorite: false, discount: 8, tags: ['推荐'], recommendationReason: '与您购买过的配件兼容' },
    { id: '8', name: '海尔双开门冰箱', price: 4299, originalPrice: 4999, rating: 4.6, reviewCount: 640, store: '海尔官方店', category: '家电', isFavorite: true, discount: 14, tags: ['节能', '静音'], recommendationReason: '根据您的浏览偏好推荐' },
  ]);

  const [categories] = useState<Category[]>([
    { id: 'c1', name: '手机数码', icon: '📱' },
    { id: 'c2', name: '电脑办公', icon: '💻' },
    { id: 'c3', name: '家用电器', icon: '🏠' },
    { id: 'c4', name: '服饰鞋包', icon: '👕' },
    { id: 'c5', name: '美妆护肤', icon: '💄' },
    { id: 'c6', name: '母婴用品', icon: '👶' },
    { id: 'c7', name: '食品生鲜', icon: '🍎' },
    { id: 'c8', name: '家居用品', icon: '🛋️' },
  ]);

  const [recommendedForYou] = useState<Product[]>([
    products[0],
    products[3],
    products[6],
    products[1],
  ]);

  const [trendingProducts] = useState<Product[]>([
    products[2],
    products[4],
    products[5],
    products[7],
  ]);

  const toggleFavorite = (productId: string) => {
    Alert.alert('收藏', `商品已${products.find(p => p.id === productId)?.isFavorite ? '取消收藏' : '收藏'}`);
  };

  const addToCart = (productId: string) => {
    Alert.alert('加入购物车', `已将商品加入购物车`);
  };

  const viewProduct = (productId: string) => {
    Alert.alert('商品详情', `查看商品: ${products.find(p => p.id === productId)?.name}`);
  };

  const renderProduct = ({ item }: { item: Product }) => (
    <TouchableOpacity style={styles.productCard} onPress={() => viewProduct(item.id)}>
      <View style={styles.productImage}>
        <Text style={styles.productImageText}>📱</Text>
      </View>
      <Text style={styles.productName} numberOfLines={2}>{item.name}</Text>
      <View style={styles.priceContainer}>
        <Text style={styles.currentPrice}>¥{item.price}</Text>
        {item.originalPrice && (
          <Text style={styles.originalPrice}>¥{item.originalPrice}</Text>
        )}
        {item.discount && (
          <Text style={styles.discountBadge}>-{item.discount}%</Text>
        )}
      </View>
      <View style={styles.productRating}>
        <Text style={styles.ratingText}>{item.rating}</Text>
        <Text style={styles.reviewCount}>({item.reviewCount})</Text>
      </View>
      <Text style={styles.storeName}>{item.store}</Text>
      <View style={styles.productTags}>
        {item.tags?.map(tag => (
          <View key={tag} style={styles.tag}>
            <Text style={styles.tagText}>{tag}</Text>
          </View>
        ))}
      </View>
      <Text style={styles.recommendationReason}>{item.recommendationReason}</Text>
      <View style={styles.productActions}>
        <TouchableOpacity 
          style={styles.favoriteButton} 
          onPress={() => toggleFavorite(item.id)}
        >
          <Text style={styles.favoriteIcon}>{item.isFavorite ? '❤️' : '🤍'}</Text>
        </TouchableOpacity>
        <TouchableOpacity 
          style={styles.cartButton} 
          onPress={() => addToCart(item.id)}
        >
          <Text style={styles.cartIcon}>🛒</Text>
        </TouchableOpacity>
      </View>
    </TouchableOpacity>
  );

  const renderCategory = ({ item }: { item: Category }) => (
    <TouchableOpacity 
      style={styles.categoryCard}
      onPress={() => Alert.alert('分类', `查看${item.name}商品`)}
    >
      <View style={styles.categoryIcon}>
        <Text style={styles.categoryIconText}>{item.icon}</Text>
      </View>
      <Text style={styles.categoryName}>{item.name}</Text>
    </TouchableOpacity>
  );

  return (
    <SafeAreaView style={styles.container}>
      {/* 头部 */}
      <View style={styles.header}>
        <Text style={styles.title}>智能推荐</Text>
        <View style={styles.headerActions}>
          <TouchableOpacity style={styles.searchButton}>
            <Text style={styles.searchIcon}>🔍</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.cartButton}>
            <Text style={styles.cartIcon}>🛒</Text>
            <View style={styles.cartBadge}>
              <Text style={styles.cartBadgeText}>3</Text>
            </View>
          </TouchableOpacity>
        </View>
      </View>

      <ScrollView style={styles.content}>
        {/* 搜索栏 */}
        <View style={styles.searchContainer}>
          <Text style={styles.searchIcon}>🔍</Text>
          <Text style={styles.searchPlaceholder}>搜索您想要的商品</Text>
        </View>

        {/* 分类导航 */}
        <Text style={styles.sectionTitle}>商品分类</Text>
        <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.categoriesContainer}>
          <View style={styles.categoriesList}>
            {categories.map(category => (
              <TouchableOpacity 
                key={category.id} 
                style={styles.categoryCard}
                onPress={() => Alert.alert('分类', `查看${category.name}商品`)}
              >
                <View style={styles.categoryIcon}>
                  <Text style={styles.categoryIconText}>{category.icon}</Text>
                </View>
                <Text style={styles.categoryName}>{category.name}</Text>
              </TouchableOpacity>
            ))}
          </View>
        </ScrollView>

        {/* 为您推荐 */}
        <Text style={styles.sectionTitle}>为您推荐</Text>
        <Text style={styles.sectionSubtitle}>根据您的喜好为您精心挑选</Text>
        <FlatList
          data={recommendedForYou}
          renderItem={renderProduct}
          keyExtractor={item => item.id}
          numColumns={2}
          columnWrapperStyle={styles.productRow}
          showsVerticalScrollIndicator={false}
          contentContainerStyle={styles.productList}
        />

        {/* 热门商品 */}
        <Text style={styles.sectionTitle}>热门推荐</Text>
        <Text style={styles.sectionSubtitle}>大家都在买的好物</Text>
        <FlatList
          data={trendingProducts}
          renderItem={renderProduct}
          keyExtractor={item => item.id}
          numColumns={2}
          columnWrapperStyle={styles.productRow}
          showsVerticalScrollIndicator={false}
          contentContainerStyle={styles.productList}
        />

        {/* 猜您喜欢 */}
        <Text style={styles.sectionTitle}>猜您喜欢</Text>
        <Text style={styles.sectionSubtitle}>根据您的浏览记录推荐</Text>
        <ScrollView 
          horizontal 
          showsHorizontalScrollIndicator={false} 
          style={styles.horizontalScroll}
          contentContainerStyle={styles.horizontalScrollContent}
        >
          {products.map(product => (
            <TouchableOpacity 
              key={product.id} 
              style={styles.horizontalProductCard}
              onPress={() => viewProduct(product.id)}
            >
              <View style={styles.horizontalProductImage}>
                <Text style={styles.productImageText}>📱</Text>
              </View>
              <Text style={styles.horizontalProductName} numberOfLines={1}>{product.name}</Text>
              <Text style={styles.horizontalProductPrice}>¥{product.price}</Text>
              <Text style={styles.recommendationReasonSmall}>{product.recommendationReason.substring(0, 15)}...</Text>
            </TouchableOpacity>
          ))}
        </ScrollView>

        {/* 推荐原因说明 */}
        <View style={styles.reasonExplanation}>
          <Text style={styles.reasonTitle}>推荐原理</Text>
          <Text style={styles.reasonText}>• 基于您的浏览历史</Text>
          <Text style={styles.reasonText}>• 考虑您的购买偏好</Text>
          <Text style={styles.reasonText}>• 结合热门趋势数据</Text>
          <Text style={styles.reasonText}>• 匹配您的兴趣标签</Text>
        </View>

        {/* 个性化设置 */}
        <View style={styles.settingsCard}>
          <Text style={styles.settingsTitle}>个性化设置</Text>
          <TouchableOpacity style={styles.settingsItem}>
            <Text style={styles.settingsItemText}>管理兴趣标签</Text>
            <Text style={styles.arrow}></Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.settingsItem}>
            <Text style={styles.settingsItemText}>调整推荐偏好</Text>
            <Text style={styles.arrow}></Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.settingsItem}>
            <Text style={styles.settingsItemText}>清除浏览历史</Text>
            <Text style={styles.arrow}></Text>
          </TouchableOpacity>
        </View>
      </ScrollView>

      {/* 底部导航 */}
      <View style={styles.bottomNav}>
        <TouchableOpacity style={[styles.navItem, styles.activeNavItem]}>
          <Text style={styles.navIcon}>🏠</Text>
          <Text style={styles.navText}>首页</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>🔍</Text>
          <Text style={styles.navText}>分类</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>🛒</Text>
          <Text style={styles.navText}>购物车</Text>
        </TouchableOpacity>
        <TouchableOpacity style={styles.navItem}>
          <Text style={styles.navIcon}>👤</Text>
          <Text style={styles.navText}>我的</Text>
        </TouchableOpacity>
      </View>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f5f7fa',
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: 16,
    backgroundColor: '#ffffff',
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  title: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#1e293b',
  },
  headerActions: {
    flexDirection: 'row',
    alignItems: 'center',
  },
  searchButton: {
    width: 36,
    height: 36,
    borderRadius: 18,
    backgroundColor: '#f1f5f9',
    alignItems: 'center',
    justifyContent: 'center',
    marginRight: 12,
  },
  cartButton: {
    width: 36,
    height: 36,
    borderRadius: 18,
    backgroundColor: '#f1f5f9',
    alignItems: 'center',
    justifyContent: 'center',
    position: 'relative',
  },
  cartBadge: {
    position: 'absolute',
    top: -4,
    right: -4,
    backgroundColor: '#ef4444',
    borderRadius: 8,
    minWidth: 16,
    height: 16,
    alignItems: 'center',
    justifyContent: 'center',
  },
  cartBadgeText: {
    color: '#ffffff',
    fontSize: 10,
    fontWeight: 'bold',
  },
  searchIcon: {
    fontSize: 18,
    color: '#64748b',
  },
  cartIcon: {
    fontSize: 18,
    color: '#64748b',
  },
  content: {
    flex: 1,
  },
  searchContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    backgroundColor: '#ffffff',
    borderRadius: 20,
    paddingVertical: 12,
    paddingHorizontal: 16,
    margin: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  searchPlaceholder: {
    fontSize: 14,
    color: '#94a3b8',
    marginLeft: 12,
    flex: 1,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    color: '#1e293b',
    marginHorizontal: 16,
    marginBottom: 4,
  },
  sectionSubtitle: {
    fontSize: 12,
    color: '#64748b',
    marginHorizontal: 16,
    marginBottom: 12,
  },
  categoriesContainer: {
    marginBottom: 16,
  },
  categoriesList: {
    flexDirection: 'row',
    paddingHorizontal: 16,
  },
  categoryCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,
    marginRight: 12,
    alignItems: 'center',
    width: 70,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  categoryIcon: {
    width: 32,
    height: 32,
    borderRadius: 16,
    backgroundColor: '#dbeafe',
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 8,
  },
  categoryIconText: {
    fontSize: 16,
    color: '#3b82f6',
  },
  categoryName: {
    fontSize: 12,
    color: '#1e293b',
    textAlign: 'center',
  },
  productList: {
    paddingHorizontal: 16,
    paddingBottom: 80,
  },
  productRow: {
    justifyContent: 'space-between',
    marginBottom: 16,
  },
  productCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 12,
    flex: 0.48,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
    position: 'relative',
  },
  productImage: {
    width: '100%',
    height: 100,
    borderRadius: 8,
    backgroundColor: '#f1f5f9',
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 8,
  },
  productImageText: {
    fontSize: 30,
  },
  productName: {
    fontSize: 14,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 8,
  },
  priceContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 4,
  },
  currentPrice: {
    fontSize: 16,
    color: '#ef4444',
    fontWeight: 'bold',
    marginRight: 8,
  },
  originalPrice: {
    fontSize: 12,
    color: '#94a3b8',
    textDecorationLine: 'line-through',
    marginRight: 8,
  },
  discountBadge: {
    fontSize: 10,
    color: '#ffffff',
    backgroundColor: '#ef4444',
    paddingHorizontal: 4,
    paddingVertical: 2,
    borderRadius: 4,
  },
  productRating: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 4,
  },
  ratingText: {
    fontSize: 12,
    color: '#f59e0b',
    marginRight: 8,
  },
  reviewCount: {
    fontSize: 12,
    color: '#64748b',
  },
  storeName: {
    fontSize: 12,
    color: '#64748b',
    marginBottom: 8,
  },
  productTags: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    marginBottom: 8,
  },
  tag: {
    backgroundColor: '#dbeafe',
    paddingHorizontal: 6,
    paddingVertical: 2,
    borderRadius: 4,
    marginRight: 4,
    marginBottom: 4,
  },
  tagText: {
    fontSize: 10,
    color: '#3b82f6',
  },
  recommendationReason: {
    fontSize: 10,
    color: '#94a3b8',
    fontStyle: 'italic',
    marginBottom: 8,
  },
  productActions: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginTop: 8,
  },
  favoriteButton: {
    padding: 8,
  },
  favoriteIcon: {
    fontSize: 20,
  },
  cartButton: {
    backgroundColor: '#3b82f6',
    paddingVertical: 8,
    paddingHorizontal: 16,
    borderRadius: 6,
    alignItems: 'center',
  },
  cartIcon: {
    fontSize: 16,
    color: '#ffffff',
  },
  horizontalScroll: {
    marginBottom: 16,
  },
  horizontalScrollContent: {
    paddingHorizontal: 16,
  },
  horizontalProductCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 12,
    width: 120,
    marginRight: 12,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  horizontalProductImage: {
    width: '100%',
    height: 80,
    borderRadius: 8,
    backgroundColor: '#f1f5f9',
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 8,
  },
  horizontalProductName: {
    fontSize: 12,
    fontWeight: '500',
    color: '#1e293b',
    marginBottom: 4,
  },
  horizontalProductPrice: {
    fontSize: 14,
    color: '#ef4444',
    fontWeight: 'bold',
    marginBottom: 4,
  },
  recommendationReasonSmall: {
    fontSize: 10,
    color: '#94a3b8',
    fontStyle: 'italic',
  },
  reasonExplanation: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,
    marginHorizontal: 16,
    marginBottom: 16,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  reasonTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 12,
  },
  reasonText: {
    fontSize: 14,
    color: '#64748b',
    lineHeight: 22,
    marginBottom: 4,
  },
  settingsCard: {
    backgroundColor: '#ffffff',
    borderRadius: 12,
    padding: 16,
    marginHorizontal: 16,
    marginBottom: 20,
    elevation: 1,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
  },
  settingsTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#1e293b',
    marginBottom: 16,
  },
  settingsItem: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#e2e8f0',
  },
  settingsItemText: {
    fontSize: 14,
    color: '#1e293b',
  },
  arrow: {
    fontSize: 18,
    color: '#94a3b8',
  },
  bottomNav: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    backgroundColor: '#ffffff',
    borderTopWidth: 1,
    borderTopColor: '#e2e8f0',
    paddingVertical: 12,
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
  },
  navItem: {
    alignItems: 'center',
    flex: 1,
  },
  activeNavItem: {
    paddingTop: 4,
    borderTopWidth: 2,
    borderTopColor: '#3b82f6',
  },
  navIcon: {
    fontSize: 20,
    color: '#94a3b8',
    marginBottom: 4,
  },
  activeNavIcon: {
    color: '#3b82f6',
  },
  navText: {
    fontSize: 12,
    color: '#94a3b8',
  },
  activeNavText: {
    color: '#3b82f6',
    fontWeight: '500',
  },
});

export default RecommendApp;

请添加图片描述


打包

接下来通过打包命令npn run harmony将reactNative的代码打包成为bundle,这样可以进行在开源鸿蒙OpenHarmony中进行使用。

在这里插入图片描述

打包之后再将打包后的鸿蒙OpenHarmony文件拷贝到鸿蒙的DevEco-Studio工程目录去:

在这里插入图片描述

最后运行效果图如下显示:

请添加图片描述
本文深入分析了基于React Native的智能推荐电商系统实现方案。系统采用TypeScript构建了包含商品核心属性和推荐原因的两层数据模型,通过React Hooks实现模块化状态管理,并优化了跨端兼容性。架构设计上使用核心组件库适配鸿蒙系统,采用Base64图标解决跨平台资源问题,利用Dimensions API确保响应式布局。文章还探讨了性能优化策略,包括useMemo缓存计算、FlatList渲染优化,以及错误处理和可访问性改进。该系统实现了功能完整、用户友好的个性化推荐界面,为React Native与鸿蒙系统的跨端开发提供了实践参考,在数据模型设计、状态管理和性能优化等方面具有示范价值。

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

Logo

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

更多推荐