一、鸿蒙页面路由核心概念

1. 路由基础与配置

鸿蒙通过@ohos/router模块实现页面跳转,核心前提是在main_pages.json中注册页面路径(所有跳转页面必须配置):

// main_pages.json

{

  "src": [

    "pages/TaskListPage", // 任务列表页(首页)

    "pages/TaskDetailPage" // 任务详情页

  ]

}

路由核心 API 说明:

API

作用

关键参数

router.pushUrl()

打开新页面(入栈)

url(页面路径)、params(传递参数)

router.backUrl()

返回上一页(出栈)

params(返回时携带参数)

router.clear()

清空路由栈

-

2. 页面参数传递

正向传递(列表页→详情页):通过pushUrl的params携带数据(支持 string/number/boolean/object 类型)

反向传递(详情页→列表页):通过backUrl的params携带返回数据,列表页通过onPageShow接收

二、跨组件状态管理:@Link 与 @Provide/@Consume

单页应用中@State足够使用,但多页 / 跨组件场景需以下装饰器:

1. @Link:父子组件双向绑定

作用:实现父子组件数据同步(修改子组件数据会同步到父组件,反之亦然)

使用场景:详情页修改任务状态,同步到列表页(父子页面关系)

语法:父组件传递时加$,子组件用@Link接收

2. @Provide/@Consume:跨层级数据共享

作用:解决多层嵌套组件的数据传递(无需层层传递参数)

使用场景:全局任务列表数据共享(列表页→详情页→子组件)

语法:@Provide(提供方,如列表页)声明数据,@Consume(消费方,如详情页子组件)接收,二者通过相同的「别名」关联

三、实战:开发任务清单 APP(完整代码)

1. 需求说明

列表页(TaskListPage):展示所有任务,点击任务进入详情页,支持新增任务

详情页(TaskDetailPage):编辑任务标题、切换完成状态,返回后列表页同步更新

状态同步:详情页修改任务后,列表页实时刷新

2. 步骤 1:定义任务数据模型

新建model/TaskModel.ets,统一数据结构:

// model/TaskModel.ets

export interface Task {

  id: string; // 任务唯一ID

  title: string; // 任务标题

  isCompleted: boolean; // 完成状态

}

3. 步骤 2:任务列表页(TaskListPage)

作为路由首页和数据提供方,使用@Provide共享任务列表:

// pages/TaskListPage.ets

import router from '@ohos/router';

import { Task } from '../model/TaskModel';

import { FlexAlign, ItemAlign } from '@ohos/ui';

@Component

export struct TaskListPage {

  // 提供全局任务数据(供详情页消费)

  @Provide('taskList') taskList: Task[] = [

    { id: '1', title: '学习鸿蒙路由', isCompleted: false },

    { id: '2', title: '掌握@Link状态绑定', isCompleted: true }

  ];

  // 接收详情页返回的参数

  onPageShow() {

    const params = router.getParams();

    if (params?.updatedTask) {

      // 详情页修改后,更新列表数据

      const updatedTask = params.updatedTask as Task;

      this.taskList = this.taskList.map(task =>

        task.id === updatedTask.id ? updatedTask : task

      );

    }

  }

  // 新增任务(简化逻辑)

  addTask() {

    this.taskList.push({

      id: Date.now().toString(),

      title: `新任务${this.taskList.length + 1}`,

      isCompleted: false

    });

  }

  build() {

    Column({ space: 20 })

      .width('100%')

      .height('100%')

      .padding(30)

      .backgroundColor('#f5f5f5') {

      // 标题与新增按钮

      Row({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {

        Text('任务清单')

          .fontSize(32)

          .fontWeight(FontWeight.Bold)

        Button('新增任务')

          .type(ButtonType.Capsule)

          .backgroundColor('#4a6cf7')

          .onClick(() => this.addTask())

      }

      // 任务列表

      List({ space: 15 }) {

        ForEach(this.taskList, (task: Task) => {

          ListItem() {

            Row({

              justifyContent: FlexAlign.SpaceBetween,

              alignItems: ItemAlign.Center

            })

              .width('100%')

              .padding(20)

              .backgroundColor('#ffffff')

              .borderRadius(12)

              .onClick(() => {

                // 跳转到详情页,传递当前任务(正向参数)

                router.pushUrl({

                  url: 'pages/TaskDetailPage',

                  params: { task: task }

                });

              }) {

              // 任务标题(完成状态划横线)

              Text(task.title)

                .fontSize(22)

                .fontColor(task.isCompleted ? '#999999' : '#333333')

                .textDecoration(task.isCompleted ? TextDecorationType.LineThrough : TextDecorationType.None)

              // 完成状态图标

              Image(task.isCompleted

                ? $r('app.media.check')

                : $r('app.media.uncheck')

              )

                .width(30)

                .height(30)

            }

          }

        })

      }

    }

  }

}

4. 步骤 3:任务详情页(TaskDetailPage)

接收列表页参数,使用@Consume获取全局任务,@Link绑定当前任务:

// pages/TaskDetailPage.ets

import router from '@ohos/router';

import { Task } from '../model/TaskModel';

import { FlexAlign, ItemAlign } from '@ohos/ui';

@Component

export struct TaskDetailPage {

  // 接收列表页传递的任务参数

  private task: Task = router.getParams().task as Task;

  // 双向绑定任务(修改后同步到列表页)

  @Link currentTask: Task = this.task;

  // 消费全局任务列表(用于获取最新数据)

  @Consume('taskList') taskList: Task[];

  build() {

    Column({ space: 40 })

      .width('100%')

      .height('100%')

      .padding(30)

      .backgroundColor('#f5f5f5') {

      // 任务标题输入框

      TextInput({

        placeholder: '输入任务标题',

        text: this.currentTask.title

      })

        .width('100%')

        .height(60)

        .padding(20)

        .backgroundColor('#ffffff')

        .borderRadius(12)

        .fontSize(22)

        .onChange((value: string) => {

          // 修改标题,双向绑定同步

          this.currentTask.title = value;

        })

      // 完成状态切换

      Row({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {

        Text('标记为已完成')

          .fontSize(22)

          .fontColor('#333333')

        Switch()

          .checked(this.currentTask.isCompleted)

          .onChange((isChecked: boolean) => {

            // 切换状态,双向绑定同步

            this.currentTask.isCompleted = isChecked;

          })

      }

      // 返回按钮(携带修改后的任务返回列表页)

      Button('保存并返回')

        .type(ButtonType.Capsule)

        .width(250)

        .height(60)

        .fontSize(22)

        .backgroundColor('#4a6cf7')

        .onClick(() => {

          // 反向传递参数,通知列表页更新

          router.backUrl({

            params: { updatedTask: this.currentTask }

          });

        })

    }

  }

}

5. 关键代码说明

(1)路由跳转与参数传递

列表页→详情页:router.pushUrl传递task对象,详情页通过router.getParams()接收

详情页→列表页:router.backUrl传递updatedTask,列表页在onPageShow中接收并更新列表

(2)状态同步核心

@Provide('taskList'):列表页提供全局任务数据,详情页通过@Consume('taskList')接收,确保数据一致性

@Link currentTask:详情页与列表页的任务对象双向绑定,修改currentTask会直接同步到列表页的taskList

四、常见问题与解决方案

1. 页面跳转失败

检查main_pages.json是否注册目标页面路径

确保pushUrl的url路径与配置一致(如pages/TaskDetailPage,不带.ets后缀)

2. 状态不同步

使用@Link时,父组件传递必须加$(如currentTask=$task)

复杂对象修改后需触发引用更新,可使用扩展运算符:this.currentTask = {...this.currentTask, title: value}

3. 参数传递类型限制

不支持传递函数、Promise 等复杂类型,建议仅传递 JSON 可序列化的数据(字符串、数字、对象、数组)

加入班级,一起学习鸿蒙

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐