《新闻资讯》一、应用分层模块化整体实现指南

HarmonyOS NEXT 新闻资讯应用分层模块化开发全指南:状态管理V2 + 分层架构实战

环境:DevEco Studio 6.1 | HarmonyOS SDK 6.1.0(23) | ArkTS
技术亮点:状态管理V2全家桶 · HdsTabs沉浸光感悬浮页签 + Navigation路由 · 分层模块化架构
适用人群:HarmonyOS中高级开发者,希望掌握最新API和架构最佳实践


效果

---

一、项目概述

1.1 项目背景

本案例参考华为官方新闻资讯应用架构设计指南,采用分层模块化架构,结合HarmonyOS 6.1最新的状态管理V2装饰器,从零构建一个功能完整的新闻资讯应用。

1.2 功能模块

模块功能点模块类型
新闻新闻列表、新闻详情、新闻分类、下拉刷新HAR
视频视频列表(Grid)、视频播放HAR
直播直播列表(关注/直播/热门三Tab)HAR
我的用户登录、评论管理、收藏、退出HAR
服务党媒云、社区融等服务HAR

1.3 技术选型

技术点选型说明
状态管理V2(@ComponentV2)替代V1的@Component,更精准的响应式更新
底部导航HdsTabs + BottomTabBarStyle@kit.UIDesignKit 悬浮页签,沉浸光感效果
页面路由Navigation + NavPathStack替代旧版router,支持声明式路由
数据懒加载LazyForEach + IDataSource性能优化的列表渲染方案
数据模型@ObservedV2 + @Trace细粒度属性级观测

二、分层模块化架构设计

2.1 三层架构

┌─────────────────────────────────────────────┐
│         产品定制层 (Product)             	   │
│    phone (HAP Entry)						  │
│    页面框架 · 导航 · 启动页 · 路由配置          │
├─────────────────────────────────────────────┤
│         基础特性层 (Features)                 │
│    news · video · live · personal · service │
│    各模块独立HAR,仅依赖common                 │
├─────────────────────────────────────────────┤
│         公共能力层 (Common)                   │
│    common (HAR)                             │
│    数据模型 · 工具类 · 常量 · 通用组件          │
└─────────────────────────────────────────────┘

2.2 模块依赖关系图

product/phone (HAP)
  ├── common (HAR)
  ├── features/news (HAR) ──→ common
  ├── features/video (HAR) ──→ common
  ├── features/live (HAR) ──→ common
  ├── features/personal (HAR) ──→ common
  └── features/service (HAR) ──→ common

核心原则

  • features层各模块互不依赖,只依赖common
  • phone模块聚合所有features,是唯一入口
  • common模块无外部依赖,是最底层基础设施

2.3 oh-package.json5 依赖配置

product/phone/oh-package.json5

{
  "dependencies": {
    "common": "file:../../common",
    "news": "file:../../features/news",
    "video": "file:../../features/video",
    "live": "file:../../features/live",
    "personal": "file:../../features/personal",
    "service": "file:../../features/service"
  }
}

features/*/oh-package.json5(每个feature模块相同):

{
  "dependencies": {
    "common": "file:../../common"
  }
}

三、状态管理V2全面应用

3.1 V1 → V2 装饰器映射表

本项目全面使用状态管理V2,以下是V1到V2的完整映射:

V1装饰器V2装饰器用途
@Component@ComponentV2组件声明
@State@Local组件本地状态
@Prop@Param父→子单向传递
@Link@Param + @Event父子双向绑定
@Provide@Provider跨层级状态提供
@Consume@Consumer跨层级状态消费
@Watch@Monitor属性变化监听
@Observed@ObservedV2 + @Trace类属性细粒度观测
计算getter@Computed计算属性
aboutToAppearaboutToAppear生命周期(不变)

3.2 数据模型设计(@ObservedV2 + @Trace)

// common/src/main/ets/model/NewsItem.ets
@ObservedV2
export class NewsItem {
  @Trace newsId: string = '';
  @Trace newsTitle: string = '';
  @Trace newsContent: string = '';
  @Trace newsTime: string = '';
  @Trace newsImage: string = '';
  @Trace category: string = '头条';
  @Trace isGood: boolean = false;
  @Trace isCollect: boolean = false;

  constructor(id: string, title: string, content: string,
    time: string, image: string, category: string = '头条') {
    this.newsId = id;
    this.newsTitle = title;
    this.newsContent = content;
    this.newsTime = time;
    this.newsImage = image;
    this.category = category;
  }
}

关键点@Trace标记的每个属性都是独立的观测单元,修改isGood不会触发仅读取newsTitle的组件重渲染。

3.3 组件间数据流

MainPage (@Provider 'pageStack')
  └── Navigation(pageStack)
        ├── HdsTabs (悬浮页签内容)
        │     ├── NewsHome    ── pushPathByName()
        │     ├── VideoHome   ── pushPathByName()
        │     ├── LiveHome
        │     └── PersonalHome ── pushPathByName()
        │
        └── navDestination(pageMap)
              ├── NewsDetail   ── @Consumer('pageStack') → pop()
              ├── VideoPlayer  ── @Consumer('pageStack') → pop()
              ├── LoginPage    ── @Consumer('pageStack') → pop()
              └── MyComments   ── @Consumer('pageStack') → pop()

四、HdsTabs 沉浸光感悬浮页签

4.1 HdsTabs 组件用法

项目使用 HdsTabs(@kit.UIDesignKit)实现底部悬浮导航,配合全局类 BottomTabBarStyleSymbolGlyphModifier 实现带图标的悬浮页签,通过 .labelStyle() 确保图标与文本颜色一致。

import { HdsTabs } from '@kit.UIDesignKit';
import { SymbolGlyphModifier } from '@kit.ArkUI';
// BottomTabBarStyle 是全局类,不需要导入

@Entry
@ComponentV2
struct MainPage {
  @Local currentTabIndex: number = 0;
  @Provider('pageStack') pageStack: NavPathStack = new NavPathStack();

  private buildTabIcon(symbol: Resource, selected: boolean): SymbolGlyphModifier {
    return new SymbolGlyphModifier(symbol)
      .fontColor([selected ? $r('app.color.focus_color') : $r('app.color.placeholder_color')]);
  }

  private buildTabBar(symbol: Resource, label: string): BottomTabBarStyle {
    return new BottomTabBarStyle({
      normal: this.buildTabIcon(symbol, false),
      selected: this.buildTabIcon(symbol, true)
    }, label).labelStyle({
      unselectedColor: $r('app.color.placeholder_color'),
      selectedColor: $r('app.color.focus_color')
    });
  }

  build() {
    Navigation(this.pageStack) {
      Column() {
        HdsTabs({ index: this.currentTabIndex }) {
          TabContent() { NewsHome() }.tabBar(this.buildTabBar($r('sys.symbol.house'), '首页'))
          TabContent() { VideoHome() }.tabBar(this.buildTabBar($r('sys.symbol.video'), '视频'))
          TabContent() { LiveHome() }.tabBar(this.buildTabBar($r('sys.symbol.video_badge_adiowaves'), '直播'))
          TabContent() { PersonalHome() }.tabBar(this.buildTabBar($r('sys.symbol.person'), '我的'))
        }
        .barOverlap(true)
        .barPosition(BarPosition.End)
        .vertical(false)
        .barFloatingStyle({ barBottomMargin: 16 })
        .onChange((index: number) => {
          this.currentTabIndex = index;
        })
        .layoutWeight(1)
      }
    }
    .hideTitleBar(true)
    .navDestination(this.pageMap)
    .mode(NavigationMode.Stack)
  }
}

4.2 关键配置说明

配置说明
HdsTabs@kit.UIDesignKit 导入
SymbolGlyphModifier@kit.ArkUI 导入,用于渲染系统图标
BottomTabBarStyle全局类,不需要导入
buildTabIcon构建带颜色的 SymbolGlyphModifier 图标
buildTabBar封装图标 + 文本 + .labelStyle() 颜色配置
.barOverlap(true)页签栏悬浮覆盖在内容之上
.barFloatingStyle()设置悬浮样式(底部间距等)
.labelStyle()设置文本选中/未选中颜色,与图标颜色保持一致

五、Navigation + NavPathStack 路由管理

5.1 路由架构

本项目使用单Navigation容器 + 统一navDestination映射的路由方案:

// 在MainPage中注册路由映射
@Builder
pageMap(name: string, param: Object) {
  if (name === 'NewsDetail') {
    NewsDetail()
  } else if (name === 'NewsCategory') {
    NewsCategory()
  } else if (name === 'VideoPlayer') {
    VideoPlayer()
  } else if (name === 'LoginPage') {
    LoginPage()
  } else if (name === 'MyComments') {
    MyComments()
  }
}

5.2 页面跳转方式

// 列表页 → 详情页(传递数据)
this.pageStack.pushPathByName('NewsDetail', newsItem);

// 详情页 → 返回
this.pageStack.pop();

5.3 启动页特殊处理

启动页(Index.ets)作为@Entry页面,通过loadContent('pages/Index')加载,其跳转使用传统router:

aboutToAppear() {
  setTimeout(() => {
    this.getUIContext().getRouter().replaceUrl({ url: 'pages/MainPage' });
  }, 1500);
}

这是因为pages/Indexpages/MainPage是同级的Entry页面,不在Navigation容器内。


六、模块间交互方式

6.1 导航交互

场景方式代码示例
Tab切换Tabs.onChangethis.currentTabIndex = index
列表→详情pushPathByNamepageStack.pushPathByName('NewsDetail', item)
详情→返回poppageStack.pop()
启动页→主页router.replaceUrlgetRouter().replaceUrl({url:'pages/MainPage'})

6.2 数据交互

数据流V2机制示例
父→子单向@ParamNewsListItem({ item: newsItem })
子→父回调@EventonCountChange: (v) => { this.count = v }
跨层级共享@Provider/@ConsumerpageStack 在MainPage提供,各子组件消费
全局状态AppStorageuserAccountnewsData评论列表

七、项目构建步骤

7.1 环境准备

  1. 安装 DevEco Studio 6.1
  2. 配置 HarmonyOS SDK 6.1.0(23)
  3. 创建空项目,SDK选择 6.1.0(23)

7.2 模块创建

build-profile.json5 中注册所有模块:

{
  "modules": [
    { "name": "phone", "srcPath": "./product/phone", "targets": [{ "name": "default", "applyToProducts": ["default"] }] },
    { "name": "common", "srcPath": "./common" },
    { "name": "news", "srcPath": "./features/news" },
    { "name": "video", "srcPath": "./features/video" },
    { "name": "live", "srcPath": "./features/live" },
    { "name": "personal", "srcPath": "./features/personal" },
    { "name": "service", "srcPath": "./features/service" }
  ]
}

7.3 路由注册

更新 product/phone/src/main/resources/base/profile/main_pages.json

{
  "src": [
    "pages/Index",
    "pages/MainPage"
  ]
}

7.4 编译运行

# DevEco Studio 中点击 Run 按钮
# 或使用命令行
hvigorw assembleHap

八、注意事项与最佳实践

8.1 @ComponentV2 注意事项

  1. 不支持 @Reusable:V2组件不能使用组件复用,用 @ObservedV2 + @Trace 的细粒度更新替代
  2. @Param 必须初始化@Param 装饰的变量必须有默认值或标记 @Require
  3. @Event 替代 callback:V2中使用 @Event 而非普通函数属性进行子→父通信

8.2 Tabs 底部导航注意事项

  1. 嵌套冲突:避免在 Tabs 内容中再次使用 Tabs 组件,会导致布局冲突
  2. LiveHome 解决方案:内部 Tab 栏改用自定义 Row + Text,避免嵌套
  3. 升级路径:待 SDK 支持后可升级为 HdsTabs 实现沉浸光感效果

8.3 NavPathStack 与 @Provider/@Consumer

  1. Provider必须在Consumer的祖先组件中
  2. key匹配@Provider('pageStack')@Consumer('pageStack') 的key必须一致
  3. NavDestination页面:通过 navDestination 注册的页面也能通过 @Consumer 获取 Provider 的值

九、总结

本项目完整演示了如何在HarmonyOS 6.1环境下,使用最新的状态管理V2分层模块化架构构建一个新闻资讯应用。核心收获:

  1. 架构清晰:三层架构(产品层/特性层/公共层)各司其职
  2. 技术前沿:全面使用V2装饰器,代码更简洁、更新更精准
  3. 稳定可靠:标准Tabs组件兼容性好,避免嵌套冲突
  4. 路由规范:Navigation + NavPathStack + @Provider + @Param 显式传参
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值