导航流程
介绍
本节解释一次导航从注册到渲染的完整流程,帮助你快速定位问题出现的位置。
运行流程
EntryAbility注册所有模块RouteGraph。NavigationHost在页面挂载时创建NavPathStack并注入到全局服务。- 业务层通过模块级
Navigator或navigateTo/navigateToForResult发起跳转。 NavigationService获取路由名称对应的构建器,构建目标页面并入栈。
入口挂载位置
入口页面负责挂载 NavigationHost,让全局导航栈生效。
ts
import { NavigationHost } from "../navigation/NavigationHost";
/**
* @file 应用首页,挂载全局 NavigationHost
*/
@Entry
@ComponentV2
struct EntryPage {
/**
* 渲染根导航容器
* @returns {void} 无返回值
*/
build(): void {
Column() {
NavigationHost();
}
}
}NavigationHost 关键逻辑
NavigationHost 负责挂载导航栈并根据路由名构建页面。
ts
import { MainPage } from "main";
import { NAV_PATH_STACK_KEY, RouteBuild, setNavPathStack } from "navigation";
/**
* @file 挂载全局导航栈
*/
@ComponentV2
export struct NavigationHost {
/**
* 全局导航栈
*/
@Provider(NAV_PATH_STACK_KEY)
navPathStack: NavPathStack = new NavPathStack();
/**
* 初始化导航栈
* @returns {void} 无返回值
*/
aboutToAppear(): void {
setNavPathStack(this.navPathStack);
}
/**
* 路由构建器映射
* @param {string} name - 路由名称
* @returns {void} 无返回值
*/
@Builder
PagesMap(name: string): void {
const builder = RouteBuild.getBuilder(name);
if (builder) {
builder.builder(); // 根据路由名渲染目标页
}
}
/**
* 渲染根导航容器
* @returns {void} 无返回值
*/
build(): void {
Navigation(this.navPathStack) {
MainPage();
}
.hideTitleBar(true)
.mode(NavigationMode.Stack)
.navDestination(this.PagesMap);
}
}业务层触发跳转
方式一:使用模块级 Navigator(推荐)
ts
import { BaseViewModel } from "base";
import { DemoNavigator } from "navigation";
import type { DemoResult } from "navigation/src/main/ets/demo/DemoResult";
/**
* @file 导航触发示例 ViewModel
*/
@ObservedV2
export default class DemoNavigationViewModel extends BaseViewModel {
/**
* 跳转到带参页面
* @returns {void} 无返回值
*/
toWithArgs(): void {
DemoNavigator.toNavigationWithArgs(1, $r("app.string.demo_goods_name"));
}
/**
* 跳转到结果回传页面
* @returns {void} 无返回值
*/
toResultPage(): void {
DemoNavigator.toNavigationResult()
.then((result?: DemoResult): void => {
if (result) {
console.info("[Navigation] result title=", result.title);
}
});
}
}方式二:直接使用 NavigationService
ts
import { BaseViewModel } from "base";
import { navigateTo, navigateToForResult } from "navigation";
import { DemoRoutes } from "navigation/src/main/ets/demo/DemoRoutes";
import type { DemoGoodsParam } from "navigation/src/main/ets/demo/DemoParam";
import type { DemoResult } from "navigation/src/main/ets/demo/DemoResult";
/**
* @file 直接调用导航服务示例 ViewModel
*/
@ObservedV2
export default class DemoNavigationViewModel extends BaseViewModel {
/**
* 直接跳转(带参)
* @returns {void} 无返回值
*/
toWithArgs(): void {
const params: DemoGoodsParam = {
goodsId: 1,
goodsName: $r("app.string.demo_goods_name")
};
navigateTo(DemoRoutes.NavigationWithArgs, params);
}
/**
* 跳转并等待回传结果
* @returns {void} 无返回值
*/
toResultPage(): void {
navigateToForResult<DemoResult>(DemoRoutes.NavigationResult)
.then((result: DemoResult | undefined) => {
if (result) {
console.info("[Navigation] result desc=", result.description);
}
});
}
}常见问题定位
- 路由跳转无响应:检查 Graph 是否注册、路由名是否一致。
- 页面白屏:检查
RouteBuild.register是否传入了正确的 Builder。 - 无法获取参数:检查是否在目标页使用
getRouteParams读取。