如何解决页面跳转无响应问题
=============

#### 问题现象

使用Navigation进行页面跳转或返回时，页面无响应，如何排查？

#### 背景知识

*   [Navigation](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-navigation)组件是路由导航的根视图容器，可以通过导航控制器[NavPathStack](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation#navpathstack10)跳转[NavDestination](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation#navdestination10)子页。
*   [pushPathByName](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation#pushpathbyname10)通过指定的路由名称将目标页面压入导航栈，并支持传递参数。
*   开发者可参考[系统路由表](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-cross-package#系统路由表)实现对系统路由表的文件配置。
*   [routerMap标签](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/module-configuration-file#routermap标签)：标识模块配置的路由表的路径。可在resources/base/profile下面定义配置文件，文件名可以自定义，例如：router\_map.json。

#### 解决方案

1.  检查父页面是否有使用Navigation组件承载路由，跳转目标页面的根节点使用NavDestination组件。
2.  检查导航控制器NavPathStack是否绑定Navigation组件。
3.  使用系统路由表时，检查resources/base/profile路径中是否创建了系统路由表配置文件；使用自定义路由表时，检查Navigation组件的[navDestination](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation#navdestination10)是否绑定路由路径与页面组件。
4.  检查跳转方法中的name（NavDestination页面名称）在系统路由表配置文件是否被正确定义。
5.  检查子页面是否自行创建NavPathStack而非复用父级栈。
    *   方法一：通过@Consume注入父级栈。
    *   方法二：在页面初始化时，通过[onReady](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navdestination#onready11)回调确保子页面和父页面为同一NavPathStack，参考[示例7（通过onReady获取栈）](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation#示例7通过onready获取栈)。
6.  代码混淆会导致无法跳转，若采用系统路由表进行跳转，则需将模块下resources/base/profile/route\_map.json文件中pageSourceFile字段对应的路径添加到白名单中。使用[\-keep-file-name](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/source-obfuscation#section-keep-file-name)来保留这些文件路径。对于API20及之后版本，不再需要手动配置白名单。
7.  Tabs嵌套Navigation时，检查是否存在多个Navigation同时绑定了同一个NavPathStack对象。

正确使用Navigation跳转可参考如下代码：

class TabNavStack {
  id: number; _// 标识符_
  navStack: NavPathStack; _//  导航栈对象。需确保每个TabContent内Navigation绑定的NavPathStack对象不同_
  content: string; _// 内容_

  constructor(id: number, navStack: NavPathStack, content: string) {
    this.id = id;
    this.navStack = navStack;
    this.content = content;
  }
}

@Entry
@Component
struct Index {
  pageStack1: NavPathStack = new NavPathStack();
  pageStack2: NavPathStack = new NavPathStack();
  pageStack3: NavPathStack = new NavPathStack();
  tabArr: TabNavStack\[\] = \[
    new TabNavStack(1, this.pageStack1, '页签1的内容'),
    new TabNavStack(2, this.pageStack2, '页签2的内容'),
    new TabNavStack(3, this.pageStack3, '页签3的内容')
  \];
  @State currentIndex: number = 0;

  @Builder
  tabBuilder(index: number) {
    Column() {
      Text(\`页签${index + 1}\`)
        .fontSize(16)
        .padding(16)
        .fontColor(this.currentIndex === index ? '#0a59f7' : '#000000');
    }
    .width('100%')
    .height('100%');
  }

  build() {
    Tabs() {
      ForEach(this.tabArr, (item: TabNavStack, index: number) => {
        TabContent() {
          NavigationComponent({ pageStack: item.navStack, content: item.content });
        }
        .tabBar(this.tabBuilder(index));
      });
    }
    .width('100%')
    .height('100%')
    .onChange((index: number) => {
      this.currentIndex = index;
    });
  }
}

@Component
struct NavigationComponent {
  pageStack: NavPathStack = new NavPathStack();
  content: string = '';

  build() {
    _// 父页面需要由Navigation承载路由_
    Column() {
      _// NavPathStack导航控制器需与Navigation绑定。_
      Navigation(this.pageStack) {
        Column() {
          Text(\`${this.content}1\`)
            .fontSize(24)
            .padding(16);
        }
        .justifyContent(FlexAlign.Center)
        .width('100%')
        .height('100%');
      }
      .clip(true)
      .hideTitleBar(true)
      .height('60%')
      .backgroundColor('#f1f3f5')
      .borderRadius(8);
      Button('跳转到下一页面', { type: ButtonType.Capsule })
        .fontSize(16)
        .height(40)
        .margin({ top: 24 })
        .onClick(() => {
          _// 传入的页面字符串与router\_map.json文件中的name是否一致，注意大小写。_
          this.pageStack.pushPathByName('PageOne', this.content, true);
        });
      Button('返回上一页', { type: ButtonType.Capsule })
        .fontSize(16)
        .margin({ top: 16 })
        .height(40)
        .onClick(() => {
          _// 传入的页面字符串与router\_map.json文件中的name是否一致，注意大小写。_
          this.pageStack.pop();
        });
    }
    .padding({ left: 16, right: 16 })
    .width('100%')
    .height('100%');
  }
}

_// 跳转页面入口函数_
@Builder
export function PageOneBuilder() {
  PageOne();
}

@Component
struct PageOne {
  _// 确保子页面可通过@Consume或参数传递共享同一个NavPathStack实例_
  pathStack: NavPathStack = new NavPathStack();
  @State content: string = '';

  build() {
    Column() {
      NavDestination() {
        Column() {
          Text(\`${this.content}2\`)
            .fontSize(24)
            .padding(16);
        }
        .justifyContent(FlexAlign.Center)
        .width('100%')
        .height('100%');
      }
      .hideBackButton(true)
      .hideTitleBar(true)
      .backgroundColor('#f1f3f5')
      .borderRadius(8)
      .onReady((context: NavDestinationContext) => {
        _// 通过onReady事件能够拿到对应的NavPathInfo和所属的NavPathStack。_
        this.pathStack = context.pathStack;
        this.content = context.pathInfo.param as string;
      });
    };
  }
}

src/main/resources/base/profile/router\_map.json配置如下所示：

{
  "routerMap": \[
    {
      "name": "PageOne",
      "pageSourceFile": "src/main/ets/pages/PageOne.ets",
      "buildFunction": "PageOneBuilder"
    }
  \]
}

效果图如下所示：

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/12/v3/bT7_Z2_4Ti6u4pbKDuu-xA/zh-cn_image_0000002658806741.png?HW-CC-KV=V1&HW-CC-Date=20260709T134111Z&HW-CC-Expire=86400&HW-CC-Sign=2404FF182F0112B6E67A1EB96305C0580F06535ABE0AFD962F0558CD40FA31EE "点击放大")