【HarmonyOS开发】Navigation使用

简介

Navigation是路由容器组件,包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。适用于模块内和跨模块的路由切换。
在页面跳转时,应该使用页面路由router,在页面内的页面跳转时,建议使用Navigation达到更好的转场动效场景。

UI框架

在这里插入图片描述

显示模式

通过mode属性来定义

Navigation() {...
}
.mode(NavigationMode.Auto)

自适应(Auto)模式

组件默认的模式,当页面宽度大于等于一定阈值( API version 9及以前:520vp,API version 10及以后:600vp )时,Navigation组件采用分栏模式,反之采用单栏模式。

单栏(Stack)模式

在这里插入图片描述

分栏(Split)模式

在这里插入图片描述

标题栏模式

通过titleMode属性设置标题栏模式,分别有Mini模式和Full模式

  • Mini模式
    在这里插入图片描述
  • Full模式
    在这里插入图片描述

菜单栏

通过menus属性进行设置。支持Array和CustomBuilder两种类型。
注意:使用Array时,竖屏最多支持3个图标,横屏最多支持5个图标

@Entry
@Component
struct Index {ToolTmp: NavigationMenuItem = {value: "",icon: "resources/base/media/startIcon.png",action: () => {}}build() {Column() {Navigation() {}.title("主标题").titleMode(NavigationTitleMode.Full).menus([this.ToolTmp,this.ToolTmp,this.ToolTmp])}.width("100%").height("100%").backgroundColor('#F1F3F5')}
}

工具栏

工具栏位于Navigation组件的底部,通过toolbarConfiguration属性进行设置。

@Entry
@Component
struct Index {ToolTmp: NavigationMenuItem = {value: "",icon: "resources/base/media/startIcon.png",action: () => {}}Toolbar: ToolbarItem = {value: "test",icon: $r('app.media.app_icon'),action: () => {}}build() {Column() {Navigation() {}.title("主标题").titleMode(NavigationTitleMode.Full).menus([this.ToolTmp,this.ToolTmp,this.ToolTmp]).toolbarConfiguration([this.Toolbar,this.Toolbar,this.Toolbar])}.width("100%").height("100%").backgroundColor('#F1F3F5')}
}

路由操作

Navigation路由相关的操作都是基于页面栈NavPathStack对象。主要涉及页面跳转、页面返回、页面替换、页面删除、参数获取、路由拦截等功能。
定义一个NavPathStack对象:pageStack: NavPathStack = new NavPathStack()
在这里插入图片描述

页面跳转

  • 普通跳转,通过页面的name去跳转
this.pageStack.pushPathByName("PageOne", "PageOne Param")
  • 带返回回调的跳转,跳转时添加onPop回调,能在页面出栈时获取返回信息,并进行处理。
this.pageStack.pushPathByName('PageOne', "PageOne Param", (popInfo) => {
console.log('Pop page name is: ' + popInfo.info.name + ', result: ' + JSON.stringify(popInfo.result))
});
  • 带错误码的跳转,跳转结束会触发异步回调,返回错误码信息。
this.pageStack.pushDestinationByName('PageOne', "PageOne Param")
.catch((error: BusinessError) => {console.error(`Push destination failed, error code = ${error.code}, error.message = ${error.message}.`);
}).then(() => {
console.error('Push destination succeed.');
});

页面返回

// 返回到上一页
this.pageStack.pop()
// 返回到上一个PageOne页面
this.pageStack.popToName("PageOne")
// 返回到索引为1的页面
this.pageStack.popToIndex(1)
// 返回到根首页(清除栈中所有页面)
this.pageStack.clear()

页面替换

this.pageStack.replacePathByName("PageOne", "PageOne Param")

页面删除

// 删除栈中name为PageOne的所有页面
this.pageStack.removeByName("PageOne")
// 删除指定索引的页面
this.pageStack.removeByIndexes([1,3,5])

页面参数获取

// 获取栈中所有页面name集合
this.pageStack.getAllPathName()
// 获取索引为1的页面参数
this.pageStack.getParamByIndex(1)
// 获取PageOne页面的参数
this.pageStack.getParamByName("PageOne")
// 获取PageOne页面的索引集合
this.pageStack.getIndexByName("PageOne")

页面转场

Navigation默认提供了页面切换的转场动画,通过页面栈操作时,会触发不同的转场效果(Dialog类型的页面默认无转场动画),Navigation也提供了关闭系统转场、自定义转场以及共享元素转场的能力。

关闭转场

  • 全局关闭
pageStack: NavPathStack = new NavPathStack()aboutToAppear(): void {this.pageStack.disableAnimation(true)
}
  • 单次关闭
pageStack: NavPathStack = new NavPathStack()this.pageStack.pushPath({ name: "PageOne" }, false)
this.pageStack.pop(false)

子页面显示类型

  • 标准类型(NavDestinationMode.STANDARD),生命周期跟随其在NavPathStack页面栈中的位置变化而改变。
  • 弹窗类型(NavDestinationMode.DIALOG),显示和消失时不会影响下层标准类型的NavDestination的显示和生命周期,两者可以同时显示。

子页面生命周期(NavDestination)

在这里插入图片描述

  • aboutToAppear:在创建自定义组件后,执行其build()函数之前执行(NavDestination创建之前),允许在该方法中改变状态变量,更改将在后续执行build()函数中生效。
  • onWillAppear:NavDestination创建后,挂载到组件树之前执行,在该方法中更改状态变量会在当前帧显示生效。
  • onAppear:通用生命周期事件,NavDestination组件挂载到组件树时执行。
  • onWillShow:NavDestination组件布局显示之前执行,此时页面不可见(应用切换到前台不会触发)。
  • onShown:NavDestination组件布局显示之后执行,此时页面已完成布局。
  • onWillHide:NavDestination组件触发隐藏之前执行(应用切换到后台不会触发)。
  • onHidden:NavDestination组件触发隐藏后执行(非栈顶页面push进栈,栈顶页面pop出栈或应用切换到后台)。
  • onWillDisappear:NavDestination组件即将销毁之前执行,如果有转场动画,会在动画前触发(栈顶页面pop出栈)。
  • onDisappear:通用生命周期事件,NavDestination组件从组件树上卸载销毁时执行。
  • aboutToDisappear:自定义组件析构销毁之前执行,不允许在该方法中改变状态变量。

使用案例

实现简单的登录界面跳转。
请添加图片描述

项目目录

在这里插入图片描述

Index

import { component_1 } from '../Components/component_1';
import { component_2 } from '../Components/component_2';
import { LoginParam } from '../Models/LoginParam';@Entry
@Component
struct Index {@Provide("pageNavigation") pageNav: NavPathStack = new NavPathStack();@BuilderPageMap(path: string) {if (path == "component_1") {component_1()}if (path == "component_2") {component_2()}}build() {Column() {Navigation(this.pageNav) {Button("直接跳转component_1界面(不带参数)").width("80%").margin({ bottom: 20 }).onClick(() => {this.pageNav.pushPathByName("component_1", "")})Button("直接跳转component_1界面(带参数)").width("80%").margin({ bottom: 20 }).onClick(() => {let login: LoginParam = new LoginParam("张三", "1234567");this.pageNav.pushPathByName("component_1", login)})}.title("主页").titleMode(NavigationTitleMode.Full).mode(NavigationMode.Auto).navDestination(this.PageMap)}.height('100%').width('100%')}
}

component_1

import { LoginParam } from '../Models/LoginParam';
import { JSON } from '@kit.ArkTS';@Component
export struct component_1 {@Consume("pageNavigation") pageNav: NavPathStack;@State login: LoginParam = new LoginParam("", "")build() {Column() {NavDestination() {Row() {Text("账户:").fontSize(16).margin({ left: 10, right: 10 })TextInput({ text: this.login.Name, placeholder: "请输入账户" }).layoutWeight(1).margin({ right: 10 }).onChange((value) => {this.login.Name = value})}.width("100%")Row() {Text("密码:").fontSize(16).margin({ left: 10, right: 10 })TextInput({ text: this.login.Password, placeholder: "请输入密码" }).layoutWeight(1).margin({ right: 10 }).type(InputType.Password).onChange((value) => {this.login.Password = value})}.width("100%").margin({ top: 20 })Grid() {GridItem() {Button("注册").width("100%").backgroundColor("#f1f2f3").fontColor("#007dfe").onClick(() => {this.pageNav.pushPathByName("component_2", this.login.Name, (popInfo) => {if (popInfo.result != null) {let popLogin: LoginParam = popInfo.result as LoginParam;if (popLogin == null) {return;}this.login = popLogin;}});})}.width("50%").padding({ right: 10, left: 10 })GridItem() {Button("登录").width("100%").onClick(() => {console.log(JSON.stringify(this.login))})}.width("50%").padding({ right: 10, left: 10 })}.rowsTemplate("1tf 1tf").margin({ top: 10 }).width("100%").height(60)}.title("登录").mode(NavDestinationMode.STANDARD).onWillShow(() => {let tempPara: LoginParam[] | string[] = this.pageNav.getParamByName("component_1") as LoginParam[] | string[]if (tempPara.length == 0 || tempPara[0] == "") {return;}this.login = tempPara[0] as LoginParam})}.width("100%").height("100%")}
}

component_2

import { LoginParam } from '../Models/LoginParam'
import { promptAction } from '@kit.ArkUI';@Component
export struct component_2 {@Consume("pageNavigation") pageNav: NavPathStack;@State login: LoginParam = new LoginParam("", "");@State tempPassword: string = "";build() {Column() {NavDestination() {Row() {Text("账户:").fontSize(16).margin({ left: 10, right: 10 }).width(40)TextInput({ text: this.login.Name, placeholder: "请输入账户" }).layoutWeight(1).margin({ right: 10 }).onChange((value) => {this.login.Name = value})}.width("100%")Row() {Text("密码:").fontSize(16).margin({ left: 10, right: 10 }).width(40)TextInput({ text: this.login.Password, placeholder: "请输入密码" }).layoutWeight(1).margin({ right: 10 }).type(InputType.Password).onChange((value) => {this.login.Password = value})}.width("100%").margin({ top: 20 })Row() {Text("确认密码:").fontSize(16).margin({ left: 10, right: 10 }).width(40)TextInput({ text: $$this.tempPassword, placeholder: "请再次输入密码" }).layoutWeight(1).margin({ right: 10 }).type(InputType.Password).onChange((value) => {this.tempPassword = value})}.width("100%").margin({ top: 20 })Column() {Button("注册").width("100%").onClick(() => {if (this.tempPassword != "" && this.tempPassword === this.login.Password && this.login.Name != "") {this.pageNav.pop(this.login)} else {promptAction.showDialog({title: "提示",message: "注册失败,密码不一致或账户为空",buttons: [{text: "确认",color: "#000"}]})}})}.width("100%").margin({ top: 20 }).padding({ right: 10, left: 10 })}.title("注册").mode(NavDestinationMode.STANDARD).onWillShow(() => {let names: string[] = this.pageNav.getParamByName("component_2") as string[];if (names == null || names.length === 0) {return;}this.login.Name = names[0]})}.width("100%").height("100%")}
}

LoginParam

@Observed
export class LoginParam {Name: string = "";Password: string = "";constructor(name: string, password: string) {this.Name = name;this.Password = password;}
}

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

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

相关文章

Spring Boot集成Spring Batch快速入门Demo

1.什么是Spring Batch? Spring Batch 是一个轻量级的开源框架,它提供了一种简单的方式来处理大量的数据。它基于Spring框架,提供了一套批处理框架,可以处理各种类型的批处理任务,如ETL、数据导入/导出、报表生成等。S…

Armv8/Armv9架构的学习大纲-学习方法-自学路线-付费学习路线

本文给大家列出了Arm架构的学习大纲、学习方法、自学路线、付费学习路线。有兴趣的可以关注,希望对您有帮助。 如果大家有需要的,欢迎关注我的CSDN课程:https://edu.csdn.net/lecturer/6964 ARM 64位架构介绍 ARM 64位架构介绍 ARM架构概况…

uniapp,vue3上传图片组件封装

首先创建一个 components 文件在里面进行组件的创建 下面是 vip组件的封装 也就是图片上传组件 只是我的命名是随便起的 <template><!--图片 --><view class"up-page"><!--图片--><view class"show-box" v-for"(item,ind…

蓝桥杯Python算法竞赛常用的函数库

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;Python关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ ​ 目录 math collectcions heapq functool itertools 常用的库函数 m…

web服务器1

&#xff08; 1 &#xff09;仅提供用户浏览的单向静态网页 单纯是由服务器单向提供数据给客户端&#xff0c; Server 不需要与 client 端有互动&#xff0c;所以你可以到该网站上去浏 览&#xff0c;但是无法进行数据的上传。 &#xff08; 2 &#xff09;提供用户互动接口的…

深入理解Linux网络(三):TCP对象创建

深入理解Linux网络&#xff08;三&#xff09;&#xff1a;TCP对象创建 TCP对象创建inet_createsock_init_data TCP对象创建 常见的三句TCP编程&#xff1a; int main() {int sk socket(AF_INET, SOCK_STREAM, 0);connect(sk, ...)recv(sk, ...) }简单的两三⾏代码&#xff…

十年前的老电脑能装win10吗_十年前的老电脑用U盘安装win10教程

十年前的老电脑能装win10吗&#xff1f;十年前的老电脑只要满足win10最低要求的配置都可以安装win10。安装win10方法很多&#xff0c;有一键重装方法、U盘安装、硬盘安装等方式&#xff0c;但最靠谱的方式还是U盘安装。十年前的老电脑用U盘安装win10首先要将u盘制作成u盘启动盘…

react自定义校验报错问题修复 ProFormText

1、以下是tsx组件 自定义校验告警导致表单无法提交问题修复 修改如下&#xff1a;

体态识别开发记录

1.多标签输出分类算法 https://aiuai.cn/aifarm1372.html 2.体态识别算法 体态对比 体态判断 2.1 3D建模的方案 stable diffusion 插件地址&#xff1a; ControlNet https://github.com/Mikubill/sd-webui-controlnet 3D Openpose https://github.com/nonnonstop/sd…

VsCode SSH远程连接服务器【内网穿透公网连接】

文章目录 1.前言2.VS code的安装和设置2.1 VS code的下载安装2.2 OpenSSH的启用2.3 为VS code配置ssh2.4 局域网内测试VS code的ssh连接2.5 Cpolar下载安装 3.Cpolar端口设置3.1 Cpolar云端设置3.2 Cpolar本地设置 4.公网访问测试5.结语 1.前言 记得笔者小时候看电视&#xff…

仿源码大师主界面UI的iAPP源文件

仿源码大师首页主界面的布局 首页&#xff0c;分类&#xff0c;需求&#xff0c;我的 就只有这几个界面内容而已 资源静态 没有任何动画和功能 纯UI布局 纯UI布局 他的最新版已经不是这个UI布局 放心使用 以学习参考为目的&#xff0c;如有不妥望告知 原创&#xff0c;纯…

【Java数据结构】线性表之栈和队列

栈&#xff08;Stack&#xff09; 简单描述 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&…

初识网络基础知识

关于网络的一些核心概念 局域网 局域网&#xff08;Local Area Network&#xff0c;简称LAN&#xff09;是一种计算机网络&#xff0c;覆盖的范围通常是相对较小的地理区域&#xff0c;比如一个办公室、一栋大楼或一个校园。 局域网的组成通常包括以下部分&#xff1a; 网络…

数据结构-C语言-排序(3)

代码位置&#xff1a;test-c-2024: 对C语言习题代码的练习 (gitee.com) 一、前言&#xff1a; 1.1-排序定义&#xff1a; 排序就是将一组杂乱无章的数据按照一定的规律&#xff08;升序或降序&#xff09;组织起来。(注&#xff1a;我们这里的排序采用的都为升序) 1.2-排序分…

录取查询老师在哪里制作?

随着考试的落幕&#xff0c;家长们焦急等待的心情终于可以稍微缓解&#xff0c;因为录取结果即将揭晓。然而&#xff0c;对于老师来说&#xff0c;这仅仅是另一项繁重工作的开始。他们需要将每一份录取通知单逐一发送给学生家长&#xff0c;这个过程不仅耗时而且容易出错。面对…

Blender中的重拓扑修改器如何使用?

许多人还不了解Blender中的重拓扑编辑器及其使用方法。Blender中的重拓扑修改器提供了一系列工具和选项&#xff0c;以简化创建优化网格的过程&#xff0c;无论是出于何种目的&#xff0c;都能为3D艺术家和建模者节省大量时间和精力。那么&#xff0c;在Blender中重拓扑的定义是…

《数据结构:C语言实现双链表》

文章目录 一、链表的分类二、双向链表1、概念与结构 三、双向链表实现1、双向链表要实现的功能2、哨兵位初始化3、双链表头插数据4、判断链表是否为空5、打印链表数据6、尾插数据7、头删数据8、尾删数据9、寻找数据所在结点10、在任意结点之后插入数据11、删除任意结点12、销毁…

FastGPT 代码调试配置

目录 一、添加 launch.json 文件 二、调试 本文简单介绍如何通过 vscode 对 FastGPT 进行调试。 这里假设已经安装 vsocde 和 FastGPT本地部署。 一、添加 launch.json 文件 vscode 打开 FastGPT 项目&#xff0c;点击 调试 -> 显示所有自动调试配置 -> 添加配置 -&…

IDEA创建Java工程、Maven安装与建立工程、Web工程、Tomcat配置

《IDEA破解、配置、使用技巧与实战教程》系列文章目录 第一章 IDEA破解与HelloWorld的实战编写 第二章 IDEA的详细设置 第三章 IDEA的工程与模块管理 第四章 IDEA的常见代码模板的使用 第五章 IDEA中常用的快捷键 第六章 IDEA的断点调试&#xff08;Debug&#xff09; 第七章 …

响应式编程(Reactive Programming)是什么?

响应式编程的概念 Reactive Programming(反应式编程或响应式编程)是一种面向数据流和变化传播的编程范式,它允许程序组件以声明式的方式响应数据的变化。 响应式编程强调以数据流作为核心,利用观察者模式等机制自动处理数据的变化和传播。 响应式编程的核心思想 以异步数…