在子窗口中使用Navigation进行多页面跳转
========================

#### 问题现象

如何在子窗口中使用Navigation实现多页面跳转的功能？

#### 背景知识

*   [Navigation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation)组件是路由导航的根视图容器，一般作为Page页面的根容器使用，其内部默认包含了标题栏、内容区和工具栏，其中内容区默认首页显示导航内容（Navigation的子组件）或非首页显示（NavDestination的子组件），首页和非首页通过路由进行切换。
*   HarmonyOS提供的窗口模块用于在同一块物理屏幕上，提供多个应用界面显示、交互的机制。开发者可以按需创建[应用子窗口](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/subwindow-guide)，如弹窗等，并对其进行属性设置等操作。
*   无法在自定义弹窗中进行多页面跳转，推荐使用子窗口进行操作。

#### 解决方案

1.  在UIAbility中的onWindowStageCreate方法中添加在如下代码，以实现窗口的全局存储。
    
    AppStorage.setAndLink('windowStage', windowStage);
    
2.  创建主页面，在该页面中实现createSubWindow方法，用以创建子窗口，设置子窗口的位置，大小及相关属性，并加载对应的页面。
    
    import { window } from '@kit.ArkUI';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    let windowStage\_: window.WindowStage | undefined = undefined;
    let sub\_windowClass: window.Window | undefined = undefined;
    
    @Entry
    @Component
    struct Index {
      private createSubWindow() {
        windowStage\_ = AppStorage.get('windowStage'); _// 获取windowStage_
    
        if (windowStage\_ == null) {
          console.error('Failed to create the subwindow. Cause: windowStage\_ is null');
        } else {
          windowStage\_.createSubWindow('mySubWindow', (err: BusinessError, data) => { _// 创建应用子窗口_
            let errCode: number = err.code;
            if (errCode) {
              console.error('Failed to create the subwindow. Cause: ' + JSON.stringify(err));
              return;
            }
            sub\_windowClass = data;
            if (!sub\_windowClass) {
              console.error('sub\_windowClass is null');
              return;
            }
            console.info('Succeeded in creating the subwindow. Data: ' + JSON.stringify(data));
            sub\_windowClass.moveWindowTo(300, 300, (err: BusinessError) => { _// 子窗口创建成功后，设置子窗口的位置、大小及相关属性等_
              let errCode: number = err.code;
              if (errCode) {
                console.error('Failed to move the window. Cause:' + JSON.stringify(err));
                return;
              }
              console.info('Succeeded in moving the window.');
            });
            sub\_windowClass.resize(700, 700, (err: BusinessError) => {
              let errCode: number = err.code;
              if (errCode) {
                console.error('Failed to change the window size. Cause:' + JSON.stringify(err));
                return;
              }
              console.info('Succeeded in changing the window size.');
            });
            sub\_windowClass.setUIContent('pages/SubWindow', (err: BusinessError) => { _// 为子窗口加载对应的目标页面。_
              let errCode: number = err.code;
              if (errCode) {
                console.error('Failed to load the content. Cause:' + JSON.stringify(err));
                return;
              }
              console.info('Succeeded in loading the content.');
              if (!sub\_windowClass) {
                console.error('sub\_windowClass is null');
                return;
              }
              sub\_windowClass.showWindow((err: BusinessError) => { _// 显示子窗口_
                let errCode: number = err.code;
                if (errCode) {
                  console.error('Failed to show the window. Cause: ' + JSON.stringify(err));
                  return;
                }
                console.info('Succeeded in showing the window.');
              });
            });
          });
        }
      }
    
      private destroySubWindow() {
        if (!sub\_windowClass) {
          console.error('sub\_windowClass is null');
          return;
        }
        sub\_windowClass.destroyWindow((err: BusinessError) => { _// 销毁子窗口_
          let errCode: number = err.code;
          if (errCode) {
            console.error('Failed to destroy the window. Cause: ' + JSON.stringify(err));
            return;
          }
          console.info('Succeeded in destroying the window.');
        });
      }
    
      build() {
        Row() {
          Column() {
            Button() {
              Text('创建子窗口')
                .fontSize(20)
                .fontWeight(FontWeight.Normal)
            }.width(110).height(50)
            .onClick(() => {
              this.createSubWindow();
            })
            .position({
              top: 50,
              left: 50
            })
    
            Button() {
              Text('销毁子窗口')
                .fontSize(20)
                .fontWeight(FontWeight.Normal)
            }.width(110).height(50)
            .onClick(() => {
              this.destroySubWindow();
            })
            .position({
              top: 120,
              left: 50
            })
          }
          .width('100%')
        }
        .height('100%')
      }
    }
    
3.  使用Navigation创建子窗口的主页面及其子页面。
    
    @Entry
    @ComponentV2
    struct SubWindow {
      pageInfos: NavPathStack = new NavPathStack();
      isUseInterception: boolean = false;
    
      build() {
        Navigation(this.pageInfos) {
          Column() {
            Button('pushPath', { stateEffect: true, type: ButtonType.Capsule })
              .width('80%')
              .height(40)
              .margin(20)
              .onClick(() => {
                this.pageInfos.pushPath({ name: 'pageOne' });
              })
          }
        }.title('子窗口页面')
        .borderWidth(2)
      }
    }
    
    class TmpClass {
      count: number = 10;
    }
    
    @Builder
    export function PageOneBuilder() {
      PageOne()
    }
    
    @ComponentV2
    export struct PageOne {
      pageInfos: NavPathStack = new NavPathStack();
    
      build() {
        NavDestination() {
          Column() {
            Button('pushPathByName', { stateEffect: true, type: ButtonType.Capsule })
              .width('80%')
              .height(40)
              .margin(20)
              .onClick(() => {
                let tmp = new TmpClass();
                this.pageInfos.pushPathByName('pageTwo', tmp);
              })
          }.width('100%').height('100%')
        }.title('pageOne')
        .onReady((context: NavDestinationContext) => {
          this.pageInfos = context.pathStack;
        })
      }
    }