鸿蒙Navigation组件用法详解(附带实例)
Navigation 是路由导航的根视图容器,通常作为页面(@Entry)的根容器,支持单栏(Stack)、分栏(Split)和自适应(Auto)三种显示模式。
Navigation 组件适用于模块内和跨模块的路由切换,通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式,以呈现更好的标题和内容联动效果。在一次开发、多端部署的场景下,Navigation 组件能够自动适配窗口显示大小,在较大窗口下自动切换为分栏展示效果。
Navigation 组件主要包含导航页(NavBar)和子页(NavDestination)。导航页由标题栏(Titlebar,包含菜单栏 menu)、内容区(Navigation 子组件)和工具栏(Toolbar)组成。导航页可以通过 hideNavBar 属性进行隐藏。导航页不存在页面栈中。导航页和子页,以及子页之间可以通过路由操作进行切换。
在 API Version 9 上,Navigation 需要配合 NavRouter 组件实现页面路由。从 API Version 10 开始,推荐使用 NavPathStack 实现页面路由。
自适应模式下,当页面宽度大于或等于一定阈值(API version 9 及以前是 520vp,API version 10 及以后是 600vp)时,Navigation 组件采用分栏模式;否则,采用单栏模式。

图 1 单页面布局示意图
将 mode 属性设置为 NavigationMode.Split,则 Navigation 组件为分栏显示模式,如下图所示。

图 2 分栏布局示意图
分栏模式组件导航的完整示例代码如下:
1) Demo.ets:
2) PageOne.ets:
3) PageTwo.ets:
4) PageThree.ets:

图 3 分栏模式组件导航的显示效果
Mini 模式表示普通型标题栏,适用于一级页面不需要突出标题的场景。Mini 模式标题栏显示效果如下图所示:

图 4 Mini模式标题栏显示效果
Mini 模式标题栏示例如下:

图 5 Full模式标题栏显示效果
Full模式标题栏示例代码如下:

图 6 设置了3个图标的菜单栏
设置了 3 个图标的菜单栏的示例代码如下:
图片也可以引用 resources 中的资源:
在竖屏中设置了 4 个图标的菜单栏的示例代码如下:

图 7 在竖屏中设置了4个图标的菜单栏显示效果
设置了 3 个图标的工具栏显示效果如下图所示:

图 8 设置了3个图标的工具栏显示效果
工具栏的示例代码如下:
Navigation 组件适用于模块内和跨模块的路由切换,通过组件级路由能力实现更加自然流畅的转场体验,并提供多种标题栏样式,以呈现更好的标题和内容联动效果。在一次开发、多端部署的场景下,Navigation 组件能够自动适配窗口显示大小,在较大窗口下自动切换为分栏展示效果。
Navigation 组件主要包含导航页(NavBar)和子页(NavDestination)。导航页由标题栏(Titlebar,包含菜单栏 menu)、内容区(Navigation 子组件)和工具栏(Toolbar)组成。导航页可以通过 hideNavBar 属性进行隐藏。导航页不存在页面栈中。导航页和子页,以及子页之间可以通过路由操作进行切换。
在 API Version 9 上,Navigation 需要配合 NavRouter 组件实现页面路由。从 API Version 10 开始,推荐使用 NavPathStack 实现页面路由。
设置页面显示模式
Navigation 组件通过 mode 属性设置页面的显示模式。默认情况下,Navigation 组件使用自适应模式,此时 mode 属性为 NavigationMode.Auto。自适应模式下,当页面宽度大于或等于一定阈值(API version 9 及以前是 520vp,API version 10 及以后是 600vp)时,Navigation 组件采用分栏模式;否则,采用单栏模式。
Navigation() {
// ...
}.mode(NavigationMode.Auto)
将 mode 属性设置为 NavigationMode.Stack,则 Navigation 组件为单页面显示模式,如下图所示。
图 1 单页面布局示意图
将 mode 属性设置为 NavigationMode.Split,则 Navigation 组件为分栏显示模式,如下图所示。

图 2 分栏布局示意图
分栏模式组件导航的完整示例代码如下:
1) Demo.ets:
@Entry
@Component
struct NavigationExample {
// 指定工具栏项目
@State toolTmp: ToolbarItem = {
value: 'func', // 按钮的名称
icon: 'image/highlight.png', // 按钮的图标
action: () => { // 按钮点击后指定的操作
}
};
// Navigation 的路由栈,页面通过压栈的方式显示,同时该类提供了控制栈中页面的方法
// 只有栈顶的页面是当前显示的页面
// 同时与子组件共享 NavPathStack 状态
@Provide('pageInfos') pageInfos: NavPathStack = new NavPathStack();
private arr: number[] = [1, 2, 3];
/**
* 根据传递名称的不同,创建和显示不同子页
* @param name 页面名称
*/
@Builder
pageMap(name: string) {
if (name === 'NavDestinationTitle1') {
PageOne();
} else if (name === 'NavDestinationTitle2') {
PageTwo();
} else if (name === 'NavDestinationTitle3') {
PageThree();
}
}
build() {
Column() {
// 导航组件,设置路由栈
Navigation(this.pageInfos) {
TextInput({ placeholder: 'search...' })
.width('90%')
.height(40)
.backgroundColor('#FFFFFF');
List({ space: 12 }) {
// 使用 ForEach 的方式为页面添加跳转的按钮
ForEach(this.arr, (item: number) => {
ListItem() {
Text('NavRouter' + item)
.width('100%')
.height(72)
.backgroundColor('#FFFFFF')
.borderRadius(24)
.fontSize(16)
.fontWeight(500)
.textAlign(TextAlign.Center)
.onClick(() => {
// 当点击按钮时,将对应子页 NavPathInfo 实例压栈
// pushPath 还有第二个参数,表示是否使用动画展示对应的子页,默认值为 true,表示使用动画
this.pageInfos.pushPath({ name: 'NavDestinationTitle' + item });
});
}
}, (item: number) => item.toString());
}
.width('90%')
.margin({ top: 12 });
}
.title('主标题') // 设置主标题
.mode(NavigationMode.Split) // 设置显示模式为分栏模式
.navDestination(this.pageMap) // 设置用户定义的子页组件
.menus([
// 单独呈现的搜索按钮
{ value: '', icon: 'image/search.png', action: () => {} },
// 单独呈现的添加按钮
{ value: '', icon: 'image/add.png', action: () => {} },
// 折叠起来的添加按钮
{ value: '', icon: 'image/add.png', action: () => {} },
// 折叠起来的添加按钮
{ value: '', icon: 'image/add.png', action: () => {} },
// 折叠起来的添加按钮
{ value: '', icon: 'image/add.png', action: () => {} }
])
// 在配置工具栏的时候,直接使用了 3 个 toolTmp 项目
// 在真正的应用场景中,工具栏项目肯定不会是相同的 3 个项目
// 图标、标题以及功能一般都会不同
.toolbarConfiguration([this.toolTmp, this.toolTmp, this.toolTmp])
}
.height('100%')
.width('100%')
.backgroundColor('#F1F3F5');
}
}
2) PageOne.ets:
@Component
export struct PageOne {
// 与父组件共享 NavPathStack 状态
@Consume('pageInfos') pageInfos: NavPathStack;
build() {
NavDestination() {
Column() {
Text('NavDestinationContent1');
}
.width('100%')
.height('100%');
}
.title('NavDestinationTitle1')
.onBackPressed(() => {
// 当与 Navigation 绑定的页面栈中存在内容时,此回调生效。当点击返回键时,触发该回调
// 返回值为 true 时,表示重写返回键逻辑;返回值为 false 时,表示回退到上一个页面
// 此处之所以返回 true,是因为此处页面要退回到由 NavPathStack 指定的页面
// 弹出路由栈的栈顶元素
const popDestinationInfo = this.pageInfos.pop();
console.log('pop 返回值 ' + JSON.stringify(popDestinationInfo));
return true;
});
}
}
3) PageTwo.ets:
@Component
export struct PageTwo {
// 与父组件共享 NavPathStack 状态
@Consume('pageInfos') pageInfos: NavPathStack;
build() {
NavDestination() {
Column() {
Text('NavDestinationContent2');
}
.width('100%')
.height('100%');
}
.title('NavDestinationTitle2')
.onBackPressed(() => {
// 当与 Navigation 绑定的页面栈中存在内容时,此回调生效。当点击返回键时,触发该回调
// 返回值为 true 时,表示重写返回键逻辑;返回值为 false 时,表示回退到上一个页面
// 此处之所以返回 true,是因为此处页面要退回到由 NavPathStack 指定的页面
// 弹出路由栈的栈顶元素
const popDestinationInfo = this.pageInfos.pop();
console.log('pop 返回值 ' + JSON.stringify(popDestinationInfo));
return true;
});
}
}
4) PageThree.ets:
@Component
export struct PageThree {
// 与父组件共享 NavPathStack 状态
@Consume('pageInfos') pageInfos: NavPathStack;
build() {
NavDestination() {
Column() {
Text('NavDestinationContent3');
}
.width('100%')
.height('100%');
}
.title('NavDestinationTitle3')
.onBackPressed(() => {
// 当与 Navigation 绑定的页面栈中存在内容时,此回调生效。当点击返回键时,触发该回调
// 返回值为 true 时,表示重写返回键逻辑;返回值为 false 时,表示回退到上一个页面
// 此处之所以返回 true,是因为此处页面要退回到由 NavPathStack 指定的页面
// 弹出路由栈的栈顶元素
const popDestinationInfo = this.pageInfos.pop();
console.log('pop 返回值 ' + JSON.stringify(popDestinationInfo));
return true;
});
}
}
显示效果如下图所示:
图 3 分栏模式组件导航的显示效果
Navigation设置标题栏模式
标题栏在界面顶部,用于呈现界面名称和操作入口。Navigation 组件通过 titleMode 属性设置标题栏模式。标题栏模式有两种:Mini 模式和 Full 模式。Mini 模式表示普通型标题栏,适用于一级页面不需要突出标题的场景。Mini 模式标题栏显示效果如下图所示:

图 4 Mini模式标题栏显示效果
Mini 模式标题栏示例如下:
Navigation() {
// ...
}.titleMode(NavigationTitleMode.Mini)
Full 模式表示强调型标题栏,适用于一级页面需要突出标题的场景。Full 模式标题栏显示效果如下图所示。
图 5 Full模式标题栏显示效果
Full模式标题栏示例代码如下:
Navigation() {
// ...
}.titleMode(NavigationTitleMode.Full)
Navigation设置菜单栏
菜单栏位于 Navigation 组件的右上角,开发者可以通过 menus 属性进行设置。menus 支持 Array<NavigationMenuItem>和CustomBuilder 两种参数类型。使用 Array<NavigationMenuItem> 类型时,竖屏最多显示 3 个图标(见下图),横屏最多显示 5 个图标,多余的图标会被放入自动生成的“更多”图标中。
图 6 设置了3个图标的菜单栏
设置了 3 个图标的菜单栏的示例代码如下:
let toolTmp: NavigationMenuItem = {'value': "", 'icon': "image/highlight.png", 'action':
()=> {}}
Navigation() {
// ...
}.menus([toolTmp, toolTmp, toolTmp])
图片也可以引用 resources 中的资源:
let toolTmp: NavigationMenuItem = {'value': "", 'icon':"resources/base/media/highlight.png", 'action': ()=> {}}
Navigation() {
// ...
}.menus([toolTmp, toolTmp, toolTmp])
在竖屏中设置了 4 个图标的菜单栏的示例代码如下:
let TooTmp: NavigationMenuItem = {'value': "", 'icon': "./image/ic_public_highlights.svg", ?'action': ()=> {}}
'action': ()=> {}}
Navigation() {
// ...
}.menus([TooTmp, TooTmp, TooTmp, TooTmp])
显示效果如下图所示:
图 7 在竖屏中设置了4个图标的菜单栏显示效果
Navigation设置工具栏
工具栏位于 Navigation 组件的底部,开发者可以通过 toolbarConfiguration 属性进行设置。设置了 3 个图标的工具栏显示效果如下图所示:

图 8 设置了3个图标的工具栏显示效果
工具栏的示例代码如下:
let toolTmp: ToolbarItem = {'value': "func", 'icon': "image/highlight.png", 'action': ()=>{}}
let toolBar: ToolbarItem[] = [toolTmp,toolTmp,toolTmp]
Navigation() {
// ...
}.toolbarConfiguration(TooBar)
ICP备案:
公安联网备案: