【最新鸿蒙应用开发】——Router页面路由

news2024/11/16 7:21:21

Router路由

页面路由指的是在应用程序中实现不同页面之间的跳转,以及数据传递。通过 Router 模块就可以实现这个功能.

img

1. 创建页面

之前是创建的文件,使用路由的时候需要创建页面,步骤略有不同

  1. 方法 1:直接右键新建Page(常用)

  2. 方法 2:单独添加页面并配置

1.1. 直接右键新建Page

创建的是页面,选项不要选错了

1.2. 单独添加页面并配置

也可以单独创建文件,然后设置为页面

  • 新建页面
pages/DetailPage.ets

@Entry
@Component
struct DetailPage {
  build() {
    Column({ space: 15 }) {
      Text('Detail Page')
        .fontSize(40)
      Button('Back')
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center)
  }
}
  •  调整配置

小技巧:

  • 按两次 shift 在弹出的界面中输入文件名,可以快速定位

{
  "src": [
    "pages/Index",
+    "pages/DetailPage"
  ]
}

TIP

  • 手动新建一个页面(ets)文件,需要在 main_pages.json 中手动配置

  • 可以自动创建(会自动添加配置)

  • 删除页面**不会自动删除配置,需要手动删除**

2. 页面跳转

接下来学习路由的跳转,页面跳转是开发过程中的一个重要组成部分。

在使用应用程序时,通常需要在不同的页面之间跳转,有时还需要将数据从一个页面传递到另一个页面。接下来咱们分场景来讲解这部分的内容:

  1. 页面跳转与后退

  2. 路由模式

  3. 参数传递

2.1. 页面跳转与后退

首先来看看看使用频率最高的 跳转和 后退,核心就是使用 router 的方法

// 1. 导入
import router from '@ohos.router';
​
// 2.调用方法-普通跳转(可以返回)
router.pushUrl({
  url:'页面地址'
})
​
// 2.调用方法-替换跳转(无法返回)
router.replaceUrl({
  url:'页面地址'
})
​
// 2.调用方法-返回()
router.back()

  1. 创建目录,管理页面:

  2. 在目录下添加:首页,详情页
  3. 页面 A 中分别使用pushUrl和replaceUrl跳转到页面 B

  4. 页面 B 测试 back 方法返回

import router from '@ohos.router'
​
@Entry
  @Component
  struct Index {
    build() {
      Column({ space: 15 }) {
        Text('首页')
          .fontSize(40)
​
        // 通过 router 模块进行跳转
        Button('去详情页-pushUrl')
          .onClick(() => {
            router.pushUrl({
              url: 'pages/day11/knowledges/router01/DetailPage',
            })
          })
        Button('去详情页-replaceUrl')
          .onClick(() => {
            router.replaceUrl({
              url: 'pages/day11/knowledges/router01/DetailPage',
            })
          })
      }
      .height('100%')
        .width('100%')
        .justifyContent(FlexAlign.Center)
​
    }
  }
import router from '@ohos.router'
​
@Entry
  @Component
  struct DetailPage {
    build() {
      Row() {
        Column() {
          Text('详情页')
            .fontSize(50)
            .fontWeight(FontWeight.Bold)
          Button('返回')
            .onClick(() => {
              router.back()
            })
        }
        .width('100%')
      }
      .height('100%')
    }
  }

router.pushUrl() 和 router.replaceUrl()。都可以跳转页面,区别为是否会替换当前页。

  • router.pushUrl():目标页面不会替换当前页,而是压入页面栈。这样可以保留当前页的状态,并且可以通过返回键或者调用router.back()方法返回到当前页。

  • router.replaceUrl():目标页面会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。

划重点:pushUrl 可以返回 replaceUrl 无法返回

2.2. 页面栈

页面栈是用来存储程序运行时页面的一种数据结构,遵循先进后出的原则,咱们结合刚刚的代码来说明一下:

页面栈的最大容量为32个页面

2.2.1. pushUrl的情况

先来看看 pushUrl的情况

  1. 默认打开首页 → 首页入栈

  2. pushUrl 去详情页 → 详情页入栈

  3. back 返回上一页 → 详情页出栈

  4. 此时页面栈中应该只有一个页面

整一个过程中,都可以 router.getLength 进行查看

img

2.2.2. replaceUrl 的情况

再来看看replaceUrl的情况

  1. 默认打开首页 → 首页入栈

  2. replaceUrl 去详情页 → 详情页替换首页,首页销毁

  3. back 无法返回 → 没有上一页

img

2.2.3. 页面栈相关 api

为了让咱们更好的获取页面栈的信息,router 模块也提供了对应的 api 以供使用

// 获取页面栈长度
router.getLength()
​
// 获取页面状态 
let page = router.getState();
console.log('current index = ' + page.index);
console.log('current name = ' + page.name);
console.log('current path = ' + page.path);
​
// 清空页面栈
router.clear()

3. 路由模式

路由提供了两种不同的跳转模式,不同模式的决定了页面是否会创建多个实例

  • standard(标准实例模式)是默认情况下的实例模式。在这种模式下,每次调用都会新建一个目标页,并压入页面栈顶。这意味着无论之前是否添加过相同的页面,每次跳转都会创建一个新的页面实例。这种模式的优点是可以确保每次跳转都是全新的页面状态,不会受到之前页面状态的影响。适用于那些需要每次跳转都呈现全新内容或状态的场景,或者需要避免复用已有页面实例导致的数据混淆问题。

  • Single(单实例模式)则会在页面栈中检查是否存在相同URL的页面。如果存在,离栈顶最近的同URL页面会被移动到栈顶,并重新加载;如果不存在,则按照标准模式跳转。这种模式的优势在于可以复用已有的页面实例,避免重复创建相同的页面,提高应用性能和资源利用率。它适用于那些需要保留页面状态或避免重复创建相同页面的场景,比如当用户在应用内多次访问同一页面时,使用Single模式可以确保页面的状态得到保持,并提供更加流畅的用户体验。

简而言之:

  1. Standard:无论之前是否添加过,一直添加到页面栈【常用】

  2. Single:如果之前加过页面,会使用之前添加的页面【看情况】

// 多实例模式下,router.RouterMode.Standard参数可以省略。
​
// pushUrl 和 replaceUrl 均可以在第二个参数设置 【路由模式】
router.pushUrl(options,mode)
router.replaceUrl(options,mode)

RouterMode参数说明

名称说明
Standard多实例模式,也是默认情况下的跳转模式。 目标页面会被添加到页面栈顶,无论栈中是否存在相同url的页面。 说明: 不使用路由跳转模式时,则按照默认的多实例模式进行跳转。
Single单实例模式。 如果目标页面的url已经存在于页面栈中,则该url页面移动到栈顶。 如果目标页面的url在页面栈中不存在同url页面,则按照默认的多实例模式进行跳转。

img

@Entry
@Component
struct HomePage {
  build() {
    Stack() {
      Image($r("app.media.douban_home"))
        .width('100%')
      Button('电影详情')
        .translate({ x: -120 })
        .onClick(() => {
​
        })
    }
    .height('100%')
  }
}
@Entry
@Component
struct MoviePage {
  @State message: string = 'Hello World';
​
  build() {
    Stack() {
      Image($r("app.media.douban_movie"))
        .width('100%')
      Button('演员')
        .translate({ x: -35, y: 180 })
        .onClick(() => {
​
        })
    }
    .height('100%')
  }
}
@Entry
@Component
struct ActorPage {
  build() {
    Stack() {
      Image($r("app.media.douban_actor"))
      Button('电影')
        .translate({ x: 43, y: 80 })
        .onClick(() => {
         
        })
    }
    .height('100%')
  }
}

3.1. Strandard模式

使用 Strandard 模式,在电影和演员页面反复跳转时会持续往页面栈中添加新的页面,浪费内存

img

3.2. Single模式

使用 Single 模式,在页面和演员页面反复跳转时会将已有的页面移到栈顶,避免浪费内存

img

4. 参数

接下来看看另外一个挺常见的需求:传递参数

日常开发中有这样的场景:点击不同的电影,商品,标题。。。跳转到与之对应的详情页面。

详情页面的布局是类似的,但是内容被替换为与之对应的内容。这就是一个常见的需要传递参数的场景:

列表 → 详情

img

4.1. 参数传递及接收

首先来看看如何实现页面参数传递和获取

// -----------传递参数------------
// 普通跳转 并 传递参数
router.pushUrl({
  url:'地址',
  params:{
    // 以对象的形式传递参数
  }
})
// 覆盖跳转并传递参数
router.replaceUrl(
  url:'地址',
  params:{
    // 以对象的形式传递参数
  }
)
// 返回并传递参数
router.back(
  url:'地址',
  params:{
    // 以对象的形式传递参数
  }
)
​
// -------------页面 B接收并解析参数------------
// aboutToAppear一会展开 (生命周期函数)
aboutToAppear(): void {
  // 1.确认内容
  console.log(JSON.stringify(router.getParams())) 
  // 2.通过 as 类型断言 转为具体的类型
  const params =  router.getParams() as 类型
  // 3. 通过点语法即可取值
  params.xxx 
} 

options参数说明

名称类型必填说明
urlstring表示目标页面的url,可以用以下两种格式: - 页面绝对路径,由配置文件中pages列表提供,例如: - pages/index/index - pages/detail/detail - 特殊值,如果url的值是"/",则跳转到首页。
paramsobject表示路由跳转时要同时传递到目标页面的数据,切换到其他页面时,当前接收的数据失效。跳转到目标页面后,使用router.getParams()获取传递的参数

img

  1. 创建目录管理页面

    1. 创建首页

    2. 创建详情页

  2. 【首页】携带数据去 【详情页】

  3. 【详情页】接收并解析数据

export class MovieInfo {
  id: number = 0
}
​
@Entry
@Component
struct Home {
  build() {
    Stack() {
      Image($r('app.media.douban_home'))
        .width('100%')
      Row({ space: 10 }) {
        Button('热辣滚烫')
          .onClick(() => {
            // id: 36081094 图片 params_movie1
​
          })
        Button('第二十条')
          .onClick(() => {
            // id: 36208094  图片 params_movie2
​
          })
        Button('飞驰人生')
          .onClick(() => {
            // id: 36369452  图片 params_movie3
​
          })
      }
      .translate({ x: -10 })
​
    }
    .height('100%')
  }
}
@Entry
@Component
struct Params {
  @State imgUrl: ResourceStr = $r('app.media.params_movie1');
​
  aboutToAppear(): void {
      // 根据 传递过来的 id 决定渲染不同的图片
      // 热辣滚烫 // id == 36081094
      // 第二十条 // id == 36208094
      // 飞驰人生 2 // id == 36369452
  }
​
  build() {
    Row() {
      Image(this.imgUrl)
    }
    .height('100%')
  }
}

5. 共享元素转场

当路由进行切换时,可以通过设置组件的 sharedTransition 属性将该元素标记为共享元素并设置对应的共享元素转场动效。

// 页面 A
组件(){
  
}
  .sharedTransition('标记', { duration: 500 })
​
// 页面 B
组件(){
  
}
  .sharedTransition('标记', { duration: 500 })

动画属性

名称参数类型是否必填参数描述
durationnumber描述共享元素转场动效播放时长。 默认值:1000。 单位:毫秒。
curveCurve | string | ICurve10+描述共享元素转场动效播放时长。 默认值:1000。 单位:毫秒。
delaynumber延迟播放时间。 默认值:0。 单位:毫秒。
motionPathMotionPathOptions运动路径信息。
zIndexnumber设置Z轴。
typeSharedTransitionEffectType动画类型。 默认值:SharedTransitionEffectType.Exchange。

效果

代码

Index.ets

import router from '@ohos.router'
​
export interface ProjectItem {
  id:number
  img: ResourceStr
  title: string
  desc: string
  sub: string
}
​
@Entry
@Component
struct Index {
  @State projectItem: ProjectItem[] = [
    {
      id:1,
      img: $r('app.media.project02'),
      title: '后台管理系统',
      desc: '以Vue技理后台后台管理系统面试题面试整理',
      sub: '后台系统'
    },
    {
      id:2,
      img: $r('app.media.project01'),
      title: '在线问医生平台(医疗类)',
      desc: '通过vue3+ts实现的在线医疗问诊相关技术整理',
      sub: 'H5项目'
    },
    {
      id:3,
      img: $r('app.media.project03'),
      title: '鸿蒙知识点',
      desc: '以ArkTS与ArkUI为主的鸿蒙基础知识点讲解',
      sub: '鸿蒙应用'
    },
  ]
​
  build() {
    Column() {
      Row() {
        Text('项目').fontSize(20)
      }
      Column() {
        ForEach(this.projectItem, (item: ProjectItem) => {
          Row({ space: 10 }) {
            Image(item.img).height('100%')
              .sharedTransition(item.id.toString(),{duration:500
              // ,type:SharedTransitionEffectType.Static
              })
            Column() {
              Column({ space: 5 }) {
                Text(item.title).fontSize(18)
                Text(item.desc).fontSize(12).fontColor('#666')
              }
              .alignItems(HorizontalAlign.Start)
​
              Text(item.sub).fontSize(10)
                .padding(3).fontColor(Color.Green)
                .backgroundColor('rgb(241, 244, 244)')
            }.height('100%')
            .alignItems(HorizontalAlign.Start)
            .justifyContent(FlexAlign.SpaceBetween)
          }.width('100%').height(110)
          .padding({ top: 15, bottom: 15 })
          .onClick(() => {
            router.pushUrl({
              url: "pages/DetailItem",
              params: item
            })
          })
        })
      }
    }.width('100%').height('100%').padding(15)
  }
}

DetailItem.ets

import router from '@ohos.router'
import { ProjectItem } from '../pages/Index'
​
@Entry
@Component
struct DetailPage {
  aboutToAppear(): void {
    const data = router.getParams() as ProjectItem
    this.data = data
  }
​
  @State data: ProjectItem = { id: 0 ,img: '', title: '', desc: '', sub: '' }
  @State isShow: boolean = true
​
  build() {
    Column() {
​
      Stack() {
        Column({ space: 30 }) {
          Row() {
            Text('<').fontColor('#fff').fontSize(30)
          }
          Row({ space: 10 }) {
            Image(this.data.img).height(150)
              .sharedTransition(this.data.id.toString(),{ duration:500
                // ,type:SharedTransitionEffectType.Static
              })
​
            Column() {
              Text(this.data.title).fontSize(20).fontColor('#fff')
              Text(this.data.desc).fontColor('#fff')
                .maxLines(2)
                .textOverflow({ overflow: TextOverflow.Ellipsis })
                .width('65%')
​
              Text(`学习进度:10%`).fontColor('#999')
            }
            .alignItems(HorizontalAlign.Start)
            .height(150).justifyContent(FlexAlign.SpaceAround)
          }
        }
        .padding(20)
        .alignItems(HorizontalAlign.Start)
​
        Image($r('app.media.project_bg'))
          .opacity(0.2).width('100%')
          .onClick(() => {
            router.back({
              url: "pages/Index"
            })
          })
      }
      .height('100%')
      .alignContent(Alignment.TopStart)
      .backgroundColor('#683a18')
      .bindSheet($$this.isShow, this.BindSheetContent(), {
        height: 520, showClose: false
      })
    }
  }
​
  @Builder
  BindSheetContent() {
    Row() {
      Text('问题列表').fontSize(25).fontWeight(500).margin(20)
    }.justifyContent(FlexAlign.Start).width('100%')
  }
}

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

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

相关文章

Java项目:基于SSM框架实现的健康综合咨询问诊平台【ssm+B/S架构+源码+数据库+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的健康综合咨询问诊平台 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…

js使用proxy代理监听控制事件

本文为proxy代理的实例应用&#xff0c;有关代理的内容可以参考&#xff1a; js语法---理解反射Reflect对象和代理Proxy对象 监听事件 要监听dom元素的事件&#xff0c;我们会采用回调触发的方式来执行操作&#xff0c; 而触发事件的过程很明显是一个异步操作&#xff0c;异…

activemq-CVE-2022-41678

Apache ActiveMQ Jolokia 后台远程代码执行漏洞 Apache ActiveMQ在5.16.5&#xff0c;5.17.3版本及以前&#xff0c;后台Jolokia存在一处任意文件写入导致的远程代码执行漏洞。 启动环境 admin/admin 方法一&#xff1a;利用poc 这个方法受到ActiveMQ版本的限制&#xff0c;因…

矢量数据库:LLMs外挂知识库

矢量数据库为管理高维数据提供了专门的解决方案&#xff0c;这对人工智能的上下文决策至关重要。但它们究竟是如何做到的呢&#xff1f; 介绍 信息有多种形式。有些信息是非结构化的&#xff0c;例如文本文档、图片和音频。有些则是结构化的&#xff0c;例如应用程序日志、表格…

【可视化大屏系列】Echarts之柱图绘制

本文为个人近期学习总结&#xff0c;若有错误之处&#xff0c;欢迎指出&#xff01; Echarts之柱图绘制 前言需求实现效果大概思路具体实现实现思路具体代码1.父组件写法2.子组件写法 附加1.同坐标系下&#xff0c;并排柱图绘制2.柱图下钻功能实现 前言 在前文页面布局、DataV…

HW期间——应急响应

01HW中应急响应的流程 001应急响应所处位置&#xff08;应急处置组&#xff09; 监控研判组发现的一些安全时间提供给应急处置组&#xff0c;应急处置组通过上机取证把线索给到溯源反制组。但是溯源反制组可能已经没有了&#xff0c;有些单位有&#xff0c;有些单位取消了。有…

标准扩散模型(standard diffusion)和潜在(latent diffusion)扩散模型的关键区别、对潜在扩散模型的认识

标准扩散模型(standard diffusion)和潜在(latent diffusion)扩散模型的关键区别、对潜在扩散模型的认识 1.两者的关键区别 潜在扩散模型通过在低维潜在空间的扩散过程&#xff0c;可以减少内存和计算的复杂性。而standard diffusion是在像素级别的空间(actual pixel space)进…

CSS上下悬浮特效

要实现一个上下悬浮的特效&#xff0c;可以使用CSS的keyframes规则和动画属性。以下是一个简单的示例&#xff1a; 代码示例 /* 定义一个名为floating的动画 */ keyframes floating {0% {transform: translateY(0); /* 初始位置 */}50% {transform: translateY(-4px); /* 向上…

吴恩达机器学习笔记2.1 - 什么是机器学习

吴恩达机器学习笔记2.1 - 什么是机器学习 最早的机器学习 1959年&#xff0c;亚瑟塞缪尔(Arthur Samuel)将机器学习定义为“Field of study that gives computers the ability to learn without being explicitly programmed”&#xff08;无需编程即可学习的研究领域&#xf…

ABAP BAPI_INCOMINGINVOICE_CREATE dump

在执行BAPI_INCOMINGINVOICE_CREATE 之后&#xff0c;正常生成了发票号&#xff0c;但是系统会dump 数据会回滚 dump如下 查阅后得知相关note:1894901 原因是在填写税行的时候&#xff0c;输入了多行&#xff0c;将数据合并为一行后即可 代码如下&#xff1a; ls_headerdat…

openlayers更改点坐标

我现在的需求是无人机点位根据ws传输的经纬度改变位置&#xff0c;在网上查了很多资料&#xff0c;终于是做出来了&#xff0c;如果有问题请指出。 效果图&#xff0c;无人机可以来回移动 这里是核心代码 // 添加飞机点位图层let vectorLayerpointfunction DronepointLayer()…

vscode设置左侧窗口字体大小

vscode设置左侧窗口字体大小 打开设置 在搜索框输入Zoom 修改这个值即可放大相关字体

从数字化营销与运营视角:看流量效果的数据分析

基于数据打通的“全链路”营销是当下的“时髦”&#xff0c;应用它的前提是什么&#xff1f;深度营销和运营的关键数据如何获得&#xff1f;如何利用数据进行更精准的营销投放&#xff1f;如何利用数据优化投放的效果&#xff1f;如何促进消费者的转化&#xff0c;以及激活留存…

【js面试题】深入理解尾递归及其在JavaScript中的应用

面试题&#xff1a;举例说明尾递归的理解&#xff0c;以及应用场景 引言&#xff1a; 在编程中&#xff0c;递归是一种常见的解决问题的方法&#xff0c;它允许函数调用自身来解决问题。然而&#xff0c;递归如果不当使用&#xff0c;可能会导致栈溢出错误&#xff0c;特别是在…

无损音频格式 FLAC 转 MP3 音频图文教程

音频文件的格式多样&#xff0c;每种格式都有其独特的特点与适用场景。FLAC&#xff08;Free Lossless Audio Codec&#xff09;&#xff0c;作为一种无损音频压缩格式&#xff0c;因其能够完美保留原始音频数据的每一个细节而备受音频发烧友和专业人士的青睐。 然而&#xff0…

代码随想录打卡第十八天

代码随想录–二叉树部分 day 17 休息日 day 18 二叉树第五天 文章目录 代码随想录--二叉树部分一、力扣654--最大二叉树二、力扣617--合并二叉树三、力扣700--二乘树中的搜素四、力扣98--验证二叉搜索树 一、力扣654–最大二叉树 代码随想录题目链接&#xff1a;代码随想录 给…

双系统ubuntu20.04扩容

windows端 打开磁盘管理器&#xff0c;选择需要的盘点击压缩卷 点击未分配的盘&#xff0c;新建简单卷&#xff0c;一致点击下一步即可&#xff0c;记住分配的大小容量 ubuntu端 lsblk 查看所有的磁盘&#xff0c;可以看到新增为nvme0n1p4、nvme1n1p2 win分配的格式为NTFS&a…

Idea-单个窗口导入并开启多个module项目

前言 大家是否有过这样的困扰&#xff0c;我们每次打开一个项目就需要单开一个idea窗口&#xff0c;项目少时了还好&#xff0c;一旦涉及多个项目间服务调用&#xff0c;特别是再包括网关、注册中心、前端web服务&#xff0c;需要开启的窗口就会是一大批&#xff0c;每次切换的…

antd a-select下拉框样式修改 vue3 亲测有效

记录一下遇到的问题 1.遇到问题&#xff1a; 使用到Vue3 Ant Design of Vue 3.2.20&#xff0c;但因为项目需求样式&#xff0c;各种查找资料都未能解决; 2.解决问题&#xff1a; ①我们审查元素可以看到&#xff0c;下拉框是在body中的; ①在a-select 元素上添加dropdownCla…

在Linux下使用Docker部署chirpstack

目录 一、前言 二、chirpstack 1、chirpstack是什么 2、chirpstack组件 3、为什么选择Docker部署 三、Linux下部署过程 四、web界面部署过程 一、前言 本篇文章我是在Linux下使用 Docker 进行部署chirpstack&#xff0c;chirpstack采用的是v4 版本&#xff0c;v4 版本 与…