1 前言
本次要完成组件导航跳转页面功能,实现设置页和主页的跳转。
2 组件导航 (Navigation)
2.1 简介
组件导航(Navigation)主要用于实现页面间以及组件内部的页面跳转,支持在不同组件间传递跳转参数,提供灵活的跳转栈操作,从而更便捷地实现对不同页面的访问和复用。本文将从组件导航(Navigation)的显示模式、路由操作、子页面管理、跨包跳转以及跳转动效等几个方面进行详细介绍。
Navigation是路由导航的根视图容器,一般作为页面(@Entry)的根容器,包括单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。Navigation组件适用于模块内和跨模块的路由切换,通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式来呈现更好的标题和内容联动效果。一次开发,多端部署场景下,Navigation组件能够自动适配窗口显示大小,在窗口较大的场景下自动切换分栏展示效果。
Navigation组件主要包含?导航页和子页。导航页由标题栏(包含菜单栏)、内容区和工具栏组成,可以通过hideNavBar属性进行隐藏,导航页不存在页面栈中,与子页,以及子页之间可以通过路由操作进行切换。
2.2 设置页面显示模式
Navigation组件通过mode属性设置页面的显示模式。
(1)自适应模式
Navigation组件默认为自适应模式,此时mode属性为NavigationMode.Auto。
(2)单页面模式
将mode属性设置为NavigationMode.Stack,Navigation组件即可设置为单页面显示模式。

(3)分栏模式
将mode属性设置为NavigationMode.Split,Navigation组件即可设置为分栏显示模式。

2.3 设置标题栏模式
标题栏在界面顶部,用于呈现界面名称和操作入口,Navigation组件通过titleMode属性设置标题栏模式。
(1)Mini模式
普通型标题栏,用于一级页面不需要突出标题的场景。
设置属性为.titleMode(NavigationTitleMode.Mini)
(2)Full模式
强调型标题栏,用于一级页面需要突出标题的场景。
设置属性为.titleMode(NavigationTitleMode.Full)
2.4 设置菜单栏
菜单栏位于Navigation组件的右上角,开发者可以通过menus属性进行设置。menus支持Array和CustomBuilder两种参数类型。使用Array类型时,竖屏最多支持显示3个图标,横屏最多支持显示5个图标,多余的图标会被放入自动生成的更多图标。
使用方法如下:(从我写的代码中摘取片段)
menus([
{
value: '设置',
icon: "resources/base/media/ic_public_settings.svg",
action: () => {
this.pageStack.pushPathByName('Settings', '')
}
},
])
2.5 页面路由功能
Navigation路由相关的操作都是基于页面栈NavPathStack提供的方法进行,每个Navigation都需要创建并传入一个NavPathStack对象,用于管理页面。主要涉及页面跳转、页面返回、页面替换、页面删除、参数获取、路由拦截等功能。
要让页面成功跳转,需要实现系统路由表。系统路由表是动态路由的一种实现方式。从API version 12开始,Navigation支持使用系统路由表的方式进行动态路由。各业务模块(HSP/HAR)中需要独立配置route_map.json文件,在触发路由跳转时,应用只需要通过NavPathStack提供的路由方法,传入需要路由的页面配置名称,此时系统会自动完成路由模块的动态加载、页面组件构建,并完成路由跳转,从而实现了开发层面的模块解耦。系统路由表不支持预览器,跨平台及模拟器。
操作步骤如下:
(1)在跳转目标模块的配置文件module.json5添加路由表配置
"routerMap": "$profile:route_map",

(2)添加完路由配置文件地址后,需要在工程resources/base/profile中创建route_map.json文件。添加如下配置信息:

{
"routerMap": [
{
"name": "Settings",
"pageSourceFile": "src/main/ets/pages/Settings.ets",
"buildFunction": "PageSettingsBuilder",
"data": {
"description": "this is setting page"
}
}
]
}
(3)在跳转目标页面中,需要配置入口Builder函数,函数名称需要和route_map.json配置文件中的buildFunction保持一致,否则在编译时会报错。
例如
@Builder
export function PageOneBuilder() {
PageOne()
}
@Component
struct PageOne {
pathStack: NavPathStack = new NavPathStack()
build() {
NavDestination() {
}
.title('PageOne')
.onReady((context: NavDestinationContext) => {
this.pathStack = context.pathStack
})
}
}
(4)创建一个页面栈对象并传入Navigation
struct Index {
pageStack: NavPathStack = new NavPathStack()
build() {
Navigation(this.pageStack) {
}
.title('Main')
}
}
(5)通过pushPathByName等路由接口进行页面跳转。
this.pageStack.pushPathByName("PageOne", "PageOne Param")
3 代码实现
3.1 Index.ets
struct Index {
scroller: Scroller = new Scroller();
@State selectCity: CityModel = { locationId: 101120201, locationName: '青岛' };
@State cityArr: CityModel[] = [
{ locationId: 101010100, locationName: '北京' }, { locationId: 101280601, locationName: '深圳' },
{ locationId: 101020100, locationName: '上海' }, { locationId: 101120201, locationName: '青岛' }];
@State weatherNow: NowWeatherModel = {
now: {
obsTime: new Date(),
temp: 0,
feelsLike: 0,
icon: 100,
text: '',
wind360: 0,
windDir: '',
windScale: '',
windSpeed: 0,
humidity: 0,
precip: 0,
pressure: 0,
vis: 0,
cloud: 0,
dew: 0
}
}
@State weatherUiModel: WeatherUiModel = {
nowTemp: 25,
nowWeatherText: '晴',
nowWeatherIcon: 100,
nowWindDir: '南风',
nowWindSpeed: 5,
nowPressure: 999,
nowVis: 10,
nowFeelTemp: 20,
nowCloud: 5,
nowHumidity: 66,
tempMax: 30,
tempMin: 20,
humidity: 50,
precip: 0.5,
hourlyTemp: [],
iconDays: [],
date: '-月-日',
day: '',
dayArr: [],
hoursArr: [],
hourlyIcon: [],
tempDayMax: [],
tempDayMin: [],
hourlyRain: []
};
@State readDataSuccess: boolean = false;
pageStack: NavPathStack = new NavPathStack()
build() {
Navigation(this.pageStack){
Scroll() {
Column() {
nowWeatherDataComponent({
selectCity: $selectCity,
cityArr: $cityArr,
weatherNow: $weatherNow,
weatherUiModel: $weatherUiModel,
readDataSuccess: $readDataSuccess
})
.margin({ bottom: 10 })
weatherData24hComponent({
readDataSuccess:$readDataSuccess,
weatherUiModel:$weatherUiModel
})
.margin({ bottom: 10 })
weatherData7dComponent({
weatherUiModel:$weatherUiModel,
readDataSuccess:$readDataSuccess
})
.margin({ bottom: 10 })
}
}
.scrollable(ScrollDirection.Vertical)
.scrollBar(BarState.Off)
.edgeEffect(EdgeEffect.None)
.backgroundColor('#ffdee0e0')
}
.backgroundColor('#ffdee0e0')
.size({ width: '100%', height: '100%' })
.title(this.selectCity.locationName+"天气")
.titleMode(NavigationTitleMode.Mini)
.hideBackButton(true)
.mode(NavigationMode.Stack)
.menus([
{
value: '设置',
icon: "resources/base/media/ic_public_settings.svg",
action: () => {
this.pageStack.pushPathByName('Settings', '')
}
},
])
}
}
3.2 设置页面Settings.ets
目前只是把组件导航功能实现了,设置页面暂时只放了个Text做演示。
@Preview({
title:'settings'
})
@Component
export struct Settings {
pageStack: NavPathStack = new NavPathStack()
build() {
NavDestination() {
Column() {
Text('settings page')
.fontSize(30)
}
}
.backgroundColor(Color.White)
.mode(NavDestinationMode.STANDARD)
.title('设置')
}
}
@Builder
export function PageSettingsBuilder(name: string, param: Object) {
Settings()
}
4 实机演示
主页标题显示是xx天气,有设置按钮

点击设置按钮可以跳转到设置页面,如下所示
