HarmonyOS 页面路由(Router)

news2024/11/25 18:39:44

1. HarmonyOS页面路由(Router)

  页面路由指在应用程序中实现不同页面之间的跳转和数据传递。HarmonyOS提供了Router模块,通过不同的url地址,可以方便地进行页面路由,轻松地访问不同的页面。本文将从页面跳转、页面返回和页面返回前增加一个询问框几个方面介绍Router模块提供的功能。
在这里插入图片描述在这里插入图片描述

1.1. 页面跳转

  页面跳转是开发过程中的一个重要组成部分。在使用应用程序时,通常需要在不同的页面之间跳转,有时还需要将数据从一个页面传递到另一个页面。

1.1.1. 跳转模式

  Router模块提供了两种跳转模式,分别是router.pushUrl()和router.replaceUrl()。这两种模式决定了目标页是否会替换当前页。
(1)router.pushUrl():目标页不会替换当前页,而是压入页面栈。这样可以保留当前页的状态,并且可以通过返回键或者调用router.back()方法返回到当前页。
(2)router.replaceUrl():目标页会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。
  说明:页面栈的最大容量为32个页面。如果超过这个限制,可以调用router.clear()方法清空历史页面栈,释放内存空间。

1.1.2.实例模式

  Router模块提供了两种实例模式,分别是Standard和Single。这两种模式决定了目标url是否会对应多个实例。
(1)Standard:标准实例模式,也是默认情况下的实例模式。每次调用该方法都会新建一个目标页,并压入栈顶。
(2)Single:单实例模式。即如果目标页的url在页面栈中已经存在同url页面,则离栈顶最近的同url页面会被移动到栈顶,并重新加载;如果目标页的url在页面栈中不存在同url页面,则按照标准模式跳转。

1.2. 场景

1.2.1.场景一

  有一个主页(Home)和一个详情页(Detail),希望从主页点击一个商品,跳转到详情页。同时,需要保留主页在页面栈中,以便返回时恢复状态。这种场景下,可以使用pushUrl()方法,并且使用Standard实例模式(或者省略)。标准实例模式下,router.RouterMode.Standard参数可以省略。

 private standardClick() {
    router.pushUrl({
      url: 'pages/myTool/RouterTwoPage' // 目标url
    }, router.RouterMode.Standard, (err) => {
      if (err) {
        console.error(`Invoke pushUrl failed, code is ${err.code},
         message is ${err.message}`);
        return;
      }
      console.info('Invoke pushUrl succeeded.');
    });
  }

1.2.2.场景二

  有一个登录页(Login)和一个个人中心页(Profile),希望从登录页成功登录后,跳转到个人中心页。同时,销毁登录页,在返回时直接退出应用。这种场景下,可以使用replaceUrl()方法,并且使用Standard实例模式(或者省略)。

  private standardReplaceClick() {
    router.replaceUrl({
      url: 'pages/myTool/RouterTwoPage'
    }, router.RouterMode.Standard, (err) => {
      if (err) {
        console.error(`Invoke replaceUrl failed, code is ${err.code},
      message is ${err.message}`);
        return;
      }
      console.info('Invoke replaceUrl succeeded.');
    })
  }

1.2.3.场景三

  有一个设置页(Setting)和一个主题切换页(Theme),希望从设置页点击主题选项,跳转到主题切换页。同时,需要保证每次只有一个主题切换页存在于页面栈中,在返回时直接回到设置页。这种场景下,可以使用pushUrl()方法,并且使用Single实例模式。

  private singleClick() {
    router.pushUrl({
      url: 'pages/myTool/RouterTwoPage'
    }, router.RouterMode.Single, (err) => {
      if (err) {
        console.error(`Invoke pushUrl failed, code is ${err.code},
         message is ${err.message}`);
        return;
      }
      console.info('Invoke pushUrl succeeded.');
    });
  }

1.2.4.场景四

  有一个搜索结果列表页(SearchResult)和一个搜索结果详情页(SearchDetail),希望从搜索结果列表页点击某一项结果,跳转到搜索结果详情页。同时,如果该结果已经被查看过,则不需要再新建一个详情页,而是直接跳转到已经存在的详情页。这种场景下,可以使用replaceUrl()方法,并且使用Single实例模式。

  private single2Click() {
  router.replaceUrl({
    url: 'pages/myTool/RouterTwoPage' // 目标url
  }, router.RouterMode.Single, (err) => {
    if (err) {
      console.error(`Invoke replaceUrl failed, code is ${err.code},
      message is ${err.message}`);
      return;
    }
    console.info('Invoke replaceUrl succeeded.');})
}

1.2.5.场景五

  如果需要在跳转时传递一些数据给目标页,则可以在调用Router模块的方法时,添加一个params属性,并指定一个对象作为参数。例如:
(1)RouterBean

export class RouterItemBean {
  id?: string
  title?: string
}
export class RouterBean {
  mainId?: string;
  routerItemBean?: RouterItemBean;
}

(2)带参跳转

 private paramsClick() {
    let paramsInfo: RouterBean = {
      mainId: "123",
      routerItemBean: {
        id: "456",
        title: "789",
      }
    };
    router.pushUrl({
      url: 'pages/myTool/RouterTwoPage', // 目标url
      params: paramsInfo // 添加params属性,传递自定义参数
    }, (err) => {
      if (err) {
        console.error(`Invoke pushUrl failed, code is ${err.code},
        message is ${err.message}`);
        return;
      }
      console.info('Invoke pushUrl succeeded.');
    })
  }

(3)在目标页中,可以通过调用Router模块的getParams()方法来获取传递过来的参数。例如:

aboutToAppear() {
    try {
      // 获取传递过来的参数对象
      this.routerBean =  (router.getParams() as RouterBean);
      let  mainId =  this.routerBean.mainId;
      let  routerItem =  this.routerBean.routerItem;
      let  id = routerItem?.id;
      let  title = routerItem?.title;
      this.msg="获取传过来的数据:"+mainId+id+title
    } catch (e) {
    }
  }

1.3.页面返回

  当用户在一个页面完成操作后,通常需要返回到上一个页面或者指定页面,这就需要用到页面返回功能。在返回的过程中,可能需要将数据传递给目标页,这就需要用到数据传递功能。

1.3.1.方式一: 返回到上一个页面

  这种方式会返回到上一个页面,即上一个页面在页面栈中的位置。但是,上一个页面必须存在于页面栈中才能够返回,否则该方法将无效。

  private routerClick() {
    //router.back(2)
    router.back()
  }

1.3.2.方式二:返回到指定页面

  这种方式可以返回到指定页面,需要指定目标页的路径。目标页必须存在于页面栈中才能够返回。

  private back2Click() {
    router.back({
      url: 'pages/myTool/RouterOnePage'
    });
  }

1.3.3.方式三:返回到指定页面,并传递自定义参数信息

  这种方式不仅可以返回到指定页面,还可以在返回的同时传递自定义参数信息。这些参数信息可以在目标页中通过调用router.getParams()方法进行获取和解析。

  private back3Click() {
    let paramsInfo: RouterBean = {
      mainId: "111",
      routerItem: {
        id: "222",
        title: "333",
      },
    };
    router.back({
      url: 'pages/myTool/RouterOnePage',
      params: paramsInfo
    });
  }

  在目标页中,在需要获取参数的位置调用router.getParams()方法即可,例如在onPageShow()生命周期回调中:

  onPageShow() {
    try {
      // 获取传递过来的参数对象
      this.routerBean =  (router.getParams() as RouterBean);
      let  mainId =  this.routerBean.mainId;
      let  routerItem =  this.routerBean.routerItem;
      let  id = routerItem?.id;
      let  title = routerItem?.title;
      this.msg="获取传过来的数据:"+mainId+id+title
    } catch (e) {
    }
  }

  当使用router.back()方法返回到指定页面时,原栈顶页面(包括)到指定页面(不包括)之间的所有页面栈都将从栈中弹出并销毁。
  另外,如果使用router.back()方法返回到原来的页面,原页面不会被重复创建,因此使用@State声明的变量不会重复声明,也不会触发页面的aboutToAppear()生命周期回调。如果需要在原页面中使用返回页面传递的自定义参数,可以在需要的位置进行参数解析。例如,在onPageShow()生命周期回调中进行参数解析。

1.4.完整代码

1.4.1.RouterBean.ets


export class RouterItem {
  id?: string
  title?: string
}

export class RouterArr {
  array?:string[]
}

export class RouterBean {
  mainId?: string;
  routerItem?: RouterItem;
  routerArr?: RouterArr;
}


1.4.2.RouterOnePage.ets

import { TitleBar } from '../../components/common/TitleBar'
import { router } from '@kit.ArkUI'
import { RouterParams } from '../../helper/RouterHelper'
import { BusinessError } from '@kit.BasicServicesKit'
import { Logger } from '../../utils/Logger'
import { RouterBean } from '../../bean/RouterBean'

@Extend(Button)
function buttonItem() {
  .stateEffect(true)
  .type(ButtonType.Normal)
  .borderRadius(8)
  .fontSize(17)
  .backgroundColor($r('app.color.primary_green'))
  .padding({
    top: 8,
    bottom: 8,
    left: 70,
    right: 70
  })
  .margin({
    top: 15,
    bottom: 15
  })
}

@Entry
@Component
struct RouterOnePage {
  @State pageTitle: string = "路由跳转"
  private routerBean?: RouterBean
  private msg: string = '3f3d4 '

  aboutToAppear() {
    try {
      this.pageTitle = (router
        .getParams() as RouterParams).title
    } catch (e) {
    }
  }
  onPageShow() {
    try {
      // 获取传递过来的参数对象
      this.routerBean =  (router.getParams() as RouterBean);
      let  mainId =  this.routerBean.mainId;
      let  routerItem =  this.routerBean.routerItem;
      let  id = routerItem?.id;
      let  title = routerItem?.title;
      this.msg="获取传过来的数据:"+mainId+id+title
    } catch (e) {
    }
  }
  /**
   * router.pushUrl()
   */
  async routerClick() {
    //router.pushUrl()
    //目标页面不会替换当前页,而是压入页面栈。
    // 这样可以保留当前页的状态,并且可以通过返回键
    // 或者调用router.back()方法返回到当前页。
    let options: router.RouterOptions = {
      url: 'pages/myTool/RouterTwoPage',
      params: new RouterParams("路由跳转", [12, 45, 78])
    }
    try {
      await router.pushUrl(options)
    } catch (err) {
      console.info(` fail callback,
      code: ${(err as BusinessError).code},
      msg: ${(err as BusinessError).message}`)
    }
  }

  /**
   * router.replaceUrl()
   */
  async replaceRouterClick() {
    router.replaceUrl({ url: 'pages/myTool/RouterTwoPage' })
      .catch((err: Error) => {
        Logger.error(JSON.stringify(err));
      })
  }

  /**
   *有一个主页(Home)和一个详情页(Detail),
   * 希望从主页点击一个商品,跳转到详情页。
   * 同时,需要保留主页在页面栈中,以便返回时恢复状态。
   * 这种场景下,可以使用pushUrl()方法,
   * 并且使用Standard实例模式(或者省略)。
   */
  private standardClick() {
    router.pushUrl({
      url: 'pages/myTool/RouterTwoPage' // 目标url
    }, router.RouterMode.Standard, (err) => {
      if (err) {
        console.error(`Invoke pushUrl failed, code is ${err.code},
         message is ${err.message}`);
        return;
      }
      console.info('Invoke pushUrl succeeded.');
    });
  }

  /**
   * 有一个登录页(Login)和一个个人中心页(Profile),
   * 希望从登录页成功登录后,跳转到个人中心页。
   * 同时,销毁登录页,在返回时直接退出应用。
   * 这种场景下,可以使用replaceUrl()方法,
   * 并且使用Standard实例模式(或者省略)。
   */
  private standardReplaceClick() {
    router.replaceUrl({
      url: 'pages/myTool/RouterTwoPage'
    }, router.RouterMode.Standard, (err) => {
      if (err) {
        console.error(`Invoke replaceUrl failed, code is ${err.code},
      message is ${err.message}`);
        return;
      }
      console.info('Invoke replaceUrl succeeded.');
    })
  }

  /**
   * 有一个设置页(Setting)和一个主题切换页(Theme),
   * 希望从设置页点击主题选项,跳转到主题切换页。
   * 同时,需要保证每次只有一个主题切换页存在于页面栈中,
   * 在返回时直接回到设置页。这种场景下,可以使用pushUrl()方法,
   * 并且使用Single实例模式。
   */
  private singleClick() {
    router.pushUrl({
      url: 'pages/myTool/RouterTwoPage'
    }, router.RouterMode.Single, (err) => {
      if (err) {
        console.error(`Invoke pushUrl failed, code is ${err.code},
         message is ${err.message}`);
        return;
      }
      console.info('Invoke pushUrl succeeded.');
    });
  }

  /**
   *有一个搜索结果列表页(SearchResult)和一个搜索结果详情页(SearchDetail),
   * 希望从搜索结果列表页点击某一项结果,跳转到搜索结果详情页。
   * 同时,如果该结果已经被查看过,则不需要再新建一个详情页,
   * 而是直接跳转到已经存在的详情页。这种场景下,可以使用replaceUrl()方法,
   * 并且使用Single实例模式。
   */
  private single2Click() {
    router.replaceUrl({
      url: 'pages/myTool/RouterTwoPage' // 目标url
    }, router.RouterMode.Single, (err) => {
      if (err) {
        console.error(`Invoke replaceUrl failed, code is ${err.code},
      message is ${err.message}`);
        return;
      }
      console.info('Invoke replaceUrl succeeded.');
    })
  }

  /**
   *如果需要在跳转时传递一些数据给目标页,则可以在调用Router模块的方法时,
   * 添加一个params属性,并指定一个对象作为参数。例如:
   */
  private paramsClick() {
    let paramsInfo: RouterBean = {
      mainId: "123",
      routerItem: {
        id: "456",
        title: "789",
      },
    };
    router.pushUrl({
      url: 'pages/myTool/RouterTwoPage', // 目标url
      params: paramsInfo // 添加params属性,传递自定义参数
    }, (err) => {
      if (err) {
        console.error(`Invoke pushUrl failed, code is ${err.code},
        message is ${err.message}`);
        return;
      }
      console.info('Invoke pushUrl succeeded.');
    })
  }

  build() {
    Column() {
      TitleBar({ pageTitle: $pageTitle })
      Button('路由跳转')
        .buttonItem()
        .onClick(this.routerClick)
      Button('销毁跳转')
        .buttonItem()
        .onClick(this.replaceRouterClick)
      Button('standard')
        .buttonItem()
        .onClick(this.standardClick)
      Button('standardReplace')
        .buttonItem()
        .onClick(this.standardReplaceClick)
      Button('single')
        .buttonItem()
        .onClick(this.singleClick)
      Button('single2')
        .buttonItem()
        .onClick(this.single2Click)
      Button('带参路由')
        .buttonItem()
        .onClick(this.paramsClick)
      Text(this.msg)
        .fontSize(18)
        .fontColor($r('app.color.primary_font_title'))
        .margin({ top: 20 })
    }
    .height('100%')
  }
}

1.4.3.RouterTwoPage.ets

import { TitleBar } from '../../components/common/TitleBar'
import { router } from '@kit.ArkUI'
import { RouterParams } from '../../helper/RouterHelper'
import { BusinessError } from '@kit.BasicServicesKit'
import { Logger } from '../../utils/Logger'
import { RouterBean } from '../../bean/RouterBean'

@Extend(Button)
function buttonItem() {
  .stateEffect(true)
  .type(ButtonType.Normal)
  .borderRadius(8)
  .fontSize(17)
  .backgroundColor($r('app.color.primary_green'))
  .padding({
    top: 8,
    bottom: 8,
    left: 70,
    right: 70
  })
  .margin({
    top: 15,
    bottom: 15
  })
}

@Entry
@Component
struct RouterTwoPage {
  @State pageTitle: string = "路由跳转二"
  private routerBean?: RouterBean
  private msg: string = '3f3d4 '

  aboutToAppear() {
    try {
      // 获取传递过来的参数对象
      this.routerBean =  (router.getParams() as RouterBean);
      let  mainId =  this.routerBean.mainId;
      let  routerItem =  this.routerBean.routerItem;
      let  id = routerItem?.id;
      let  title = routerItem?.title;
      this.msg="获取传过来的数据:"+mainId+id+title
    } catch (e) {
    }
  }

  /**
   * 返回到上一个页面
   */
  private backClick() {
    //router.back(2)
    router.back()
  }
  /**
   * 返回指定页面
   */
  private back2Click() {
    router.back({
      url: 'pages/myTool/RouterOnePage'
    });
  }
  /**
   *  返回到指定页面,并传递自定义参数信息
   */
  private back3Click() {
    let paramsInfo: RouterBean = {
      mainId: "111",
      routerItem: {
        id: "222",
        title: "333",
      },
    };
    router.back({
      url: 'pages/myTool/RouterOnePage',
      params: paramsInfo
    });
  }

  build() {
    Column() {
      TitleBar({ pageTitle: $pageTitle })
      Button('返回到上一个页面')
        .buttonItem()
        .onClick(this.backClick)
      Button('返回指定页面')
        .buttonItem()
        .onClick(this.back2Click)
      Button('传参返回')
        .buttonItem()
        .onClick(this.back3Click)
      Text(this.msg)
        .fontSize(18)
        .fontColor($r('app.color.primary_font_title'))
        .margin({ top: 20 })
    }
    .height('100%')
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1835401.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LeetCode刷题之HOT100之单词拆分

上午把docker基础学完了。下午来了闲的无聊,做一题先。 1、题目描述 2、逻辑分析 这个问题是一个典型的动态规划问题,我们可以使用一个布尔数组 dp 来记录字符串 s 的前缀是否可以被拆分成字典中的单词。具体地,dp[i] 表示字符串 s 的前 i …

Odrivegui 、odrivetool运行时的几个问题(windows)

ODrivetool 遇到的几个问题 错误信息 Traceback (most recent call last): File “c:\Users\hpf\Desktop\import matplotlib.py”, line 1, in import matplotlib.pyplot as plt File “C:\Users\hpf\AppData\Local\Programs\Python\Python39\lib\site-packages\matplotlib_…

【STM32】使用标准库点亮LED

1.硬件设计 LED1的阴极接到了PC13引脚上,我们控制PC13引脚的电平输出状态,即可控制LED1的亮灭。 2.编程要点 使能GPIO端口时钟;初始化GPIO目标引脚为推挽输出模式;编写简单测试程序,控制GPIO引脚输出高、低电平。 查…

数据驱动决策:工单统计工具如何赋能企业精准运营

在当今这个数字化飞速发展的时代,企业对于内部运营效率的追求已经达到了前所未有的高度。你是否曾为了繁杂的工单统计管理而头疼不已?是否曾因为无法准确进行工单统计数据而错失商机?今天,我将向你展示一款革命性的工单统计工具&a…

Python基础教程——20个让人眼前一亮的逻辑妙用!

文末免费赠精品编程资料~~ Python不仅仅是一种编程语言,它还是解决问题的艺术,充满了让人拍案叫绝的“小巧思”。通过这15个小技巧,你不仅能提升编程技能,还能让你的代码更加优雅、高效。让我们一探究竟吧! 1. 列表推…

Thinkphp校园新闻发布系统源码 毕业设计项目实例

Thinkphp校园新闻发布系统源码 毕业设计项目实例 校园新闻发布系统模块: 用户模块:注册,登陆,查看个人信息,修改个人信息,站内搜索,新闻浏览等功能, 后台管理员模块:会员…

挖矿宝藏之开发者模式

目录 一、开发者模式简介 二、启动方式 三、元素(Elements) 四、控制台(Console) 五、来源(Sources) 六、网络(Network) 七、性能(Performance) 八、…

谷粒商城实战(043集群学习-mysql集群-分库分表)

Java项目《谷粒商城》架构师级Java项目实战,对标阿里P6-P7,全网最强 总时长 104:45:00 共408P 此文章包含第364p-第p365的内容 分库分表 这种基本无人用 shardingSphere shard(碎片) sphere (球) sh…

基于Spring Boot+VUE论坛管理系统

1前台首页功能模块 论坛管理系统,在系统首页可以查看首页、公告、热门帖子、论坛新天地、新闻资讯、留言反馈、个人中心、后台管理、客服中心等内容,如图1所示。 图1前台首页功能界面图 用户登录、用户注册,在注册页面可以填写账号、密码、昵…

手写一个JSON可视化工具

前言 JSON 平时大家都会用到,都不陌生,今天就一起来实现一个 JSON 的可视化工具。 大概长成下面的样子: 树展示 相比于现有的一些 JSON 格式化工具,我们今天制作的这个小工具会把 JSON 转为树去表示。其中: 橙色标…

生命在于学习——Python人工智能原理(3.5)

三、深度学习 9、常见神经网络 常见的神经网络有卷积神经网络(AlexNet、VGGNet)、循环神经网络(RNN) 长短时记忆网络(LSTM)。 (1)AlexNet AlexNet于2012年由Hinton学生Alex提出&a…

DolphinScheduler日志乱码、worker日志太多磁盘报警、版本更新导致不兼容怎么办?

作者 | 刘宇星 本文作者总结了在使用Apache DolphinScheduler过程中遇见过的常见问题及其解决方案,包括日志出现乱码、worker日志太多磁盘报警、版本更新导致不兼容问题等,快来看看有没有困扰你想要的答案吧! DolphinScheduler集群环境有多…

背就有效!2024下《系统架构设计师》50个高频考点汇总

宝子们!上半年软考已经结束一段时间了,准备备考下半年软考高级-系统架构设计师的小伙伴可以开始准备了,毕竟高级科目的难度可是不低的,相信参加过上半年架构的小伙伴深有体会。 这里给大家整理了50个高频考点,涵盖全书…

月薪没到20K,必啃的WebGIS系统技术栈,你练到哪一步了?

WebGIS(网络地理信息系统)是目前地理信息系统(GIS)开发的主流,它利用互联网技术来发布、共享和交互地理空间数据。 一个完整的WebGIS项目通常涉及以下几个主要环节:具备一定的理论知识,数据生产…

数据压缩还能这么玩,国产数据库有救了!

页级压缩 opengauss数据库是以数据页面(Page)为单位进行压缩解压,本特性自openGauss 3.0.0版本开始引入,通过对数据页的透明页压缩和维护页面存储位置的方式,做到高压缩、高性能。提高数据库对磁盘的利用率。 页级压缩…

文心一言 VS 讯飞星火 VS chatgpt (284)-- 算法导论21.2 2题

二、对定理 21.1 的整体证明进行改造,得到使用链表表示和加权合并启发式策略下的 MAKE-SET 和 FIND-SET 的摊还时间上界为 O(1),以及 UNION 的摊还时间上界为 O(lgn)。如果要写代码,请用go语言。 文心一言: 在Go语言中实现使用链…

Golang——channel

channel是Go在语言层面提供的协程间的通信方式。通过channel我们可以实现多个协程之间的通信,并对协程进行并发控制。 使用注意: 管道没有缓冲区时,从管道中读取数据会阻塞,直到有协程向管道中写入数据。类似地,向管道…

Java快速开发:力推开源项目若依RuoYi

在Java开发开源框架中,首屈一指的应该若依,在行业里,不管小公司中公司还是大公司,都能够看到若依项目的身影。足以见得 若依框架的受众之大。 RuoYi-Cloud RuoYi-Cloud 是一个 Java EE 分布式微服务架构平台,基于经典…

轻兔推荐 —— who.cx

via:轻兔推荐 - https://app.lighttools.net/ 简介 who.cx是一个域名whois查询工具,界面简洁,可查询域名基本信息,注册续费价格,支持查看一级域名解析记录 - 对于已注册域名可以查看注册商注册时间、 过期时间等基础信…

大多数JAVA程序员都干不到35岁吗?

在开始前刚好我有一些资料,是我根据网友给的问题精心整理了一份「java的资料从专业入门到高级教程」, 点个关注在评论区回复“666”之后私信回复“666”,全部无偿共享给大家!!! 很遗憾是的,对…