子窗口控制主窗口的页面跳转
=============

#### 问题现象

页面中有子窗口的场景下，需要通过Router操作主窗口页面，但是调用pushUrl、replaceUrl等方法后，操作的是子窗口的页面，怎么才能获取到主窗口的Router对象操作主窗口的页面？

#### 效果预览

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/91/v3/94Mn0xSESM-k1O0_lE6lZA/zh-cn_image_0000002658969081.png?HW-CC-KV=V1&HW-CC-Date=20260709T134008Z&HW-CC-Expire=86400&HW-CC-Sign=D12480BEABB848D82C6E2F7B5D07134D6A75CE1193BD45C2D4FE156EBAD35F52 "点击放大")

#### 背景知识

*   [Router](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-router)提供通过不同的url访问不同的页面，包括跳转到应用内的指定页面、同应用内的某个页面替换当前页面、返回上一页面或指定的页面等。
*   [createSubWindow](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-window-windowstage#createsubwindow9)：可以创建当前WindowStage实例下的子窗口。

#### 解决方案

子窗口和主窗口是两个独立的路由栈，子窗口中使用[pushUrl](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-router#pushurl)、[back](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-router#back12)等方法只能控制子窗口页面的跳转和返回。

若需要在子窗口控制主窗口页面跳转，需要在子窗口中获取到主窗口的路由栈。

1.  在EntryAbility中的onWindowStageCreate方法中使用AppStorage保存WindowStage实例。
    
    import { ConfigurationConstant, UIAbility } from '@kit.AbilityKit';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    import { window } from '@kit.ArkUI';
    
    const DOMAIN \= 0x0000;
    
    export default class EntryAbility extends UIAbility {
      onCreate(): void {
        try {
          this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR\_MODE\_NOT\_SET);
        } catch (err) {
          hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
        }
        hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
      }
    
      onDestroy(): void {
        hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
      }
    
      onWindowStageCreate(windowStage: window.WindowStage): void {
      _  // Main window is created, set main page for this ability_
        hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
       _ // 第一步：通过AppStorage保存WindowStage实例_
        AppStorage.setOrCreate('windowStage', windowStage);
        windowStage.loadContent('pages/SubWindowDemo', (err) \=\> {
          if (err.code) {
            hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
            return;
          }
          hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
        });
      }
    
      onWindowStageDestroy(): void {
        _// Main window is destroyed, release UI related resources_
        hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
      }
    
      onForeground(): void {
     _   // Ability has brought to foreground_
        hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
      }
    
      onBackground(): void {
      _  // Ability has back to background_
        hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
      }
    };
    

2.  创建子窗口需要加载的页面SubWindowPage.ets，在该页面中获取WindowStage实例下的主窗口对象，通过[getUIContext()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-custom-component-api#getuicontext)获取UIContext实例，再通过[getRouter()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-uicontext-uicontext#getrouter)获取Router对象。
    
    import { router, window } from '@kit.ArkUI';
    
    @Entry
    @Component
    struct SubWindowPage {
    
      onBackPress(): boolean | void {
     _   // 侧滑返回首页_
        let uiContext: UIContext | null \= null;
        let windowStage \= AppStorage.get('windowStage') as window.WindowStage;
        _// 通过getMainWindowSync获取WindowStage实例下的主窗口_
        let windowClass: window.Window \= windowStage.getMainWindowSync();
        uiContext \= windowClass.getUIContext();
      _  // 获取Router对象_
        uiContext.getRouter().pushUrl({
          url: 'pages/SubWindowDemo',
        }, router.RouterMode.Single);
      }
    
      build() {
        Column({ space: 10 }) {
          Text('子窗口 SubWindow');
          Button('主窗口页面跳转')
            .onClick(() \=\> {
              try {
                console.info('主窗口页面跳转');
                let uiContext: UIContext | null \= null;
                let windowStage \= AppStorage.get('windowStage') as window.WindowStage;
               _ // 通过getMainWindowSync获取WindowStage实例下的主窗口_
                let windowClass: window.Window \= windowStage.getMainWindowSync();
                uiContext \= windowClass.getUIContext();
              _  // 获取Router对象_
                uiContext.getRouter().pushUrl({
                  url: 'pages/Page', _// 需要自行创建一个Page页面_
                }, router.RouterMode.Single);
              } catch (exception) {
                console.error(\`Failed to create the subwindow. Cause code: ${exception.code}, message: ${exception.message}\`);
              };
            });
        }
        .borderRadius('16vp')
        .backgroundColor('#F1F3F5')
        .justifyContent(FlexAlign.Center)
        .height('100%')
        .width('100%')
      }
    }
    
3.  在SubWindowDemo.ets文件中，创建子窗口，并通过[loadContent](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-window-window#loadcontent9)方法加载步骤2创建的SubWindowPage页面。
    
    import { display, window } from '@kit.ArkUI';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    @Entry
    @Component
    struct SubWindowDemo {
      build() {
        Column() {
          Button('创建子窗口')
            .onClick(() \=\> {
              let windowStage \= AppStorage.get('windowStage') as window.WindowStage;
              try {
                windowStage.createSubWindow('mySubWindow').then((windowClass: window.Window) \=\> {
                  windowClass.loadContent('pages/SubWindowPage', null);
                  const screenWidth \= display.getDefaultDisplaySync().width;
                 _ // 子窗口居中_
                  windowClass.moveWindowTo(screenWidth / 2 \- this.getUIContext().vp2px(200) / 2, 400);
                _  // 设置子窗口大小_
                  windowClass.resize(this.getUIContext().vp2px(200), this.getUIContext().vp2px(200));
                  _//_ _展示子窗口_
                  windowClass.showWindow();
                  console.info(\`Succeeded in creating the subwindow. Data: ${JSON.stringify(windowClass)}\`);
                }).catch((err: BusinessError) \=\> {
                  console.error(\`Failed to create the subwindow. Cause code: ${err.code}, message: ${err.message}\`);
                });
              } catch (exception) {
                console.error(\`Failed to create the subwindow. Cause code: ${exception.code}, message: ${exception.message}\`);
              }
            })
        }
        .justifyContent(FlexAlign.Center)
        .height('100%')
        .width('100%')
      }
    }