分栏模式下，页面切换无响应
=============

#### 问题现象

在分栏模式下，点击左侧新闻时，右侧页面能正常显示该新闻；但点击另一条新闻后，右侧页面仍保持显示上一条新闻内容。

#### 背景知识

*   [onNewParam](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navdestination#onnewparam19)栈中的NavDestination页面通过launchMode.MOVE\_TO\_TOP\_SINGLETON或launchMode.POP\_TO\_SINGLETON移动到栈顶时，触发该回调。
*   [pushPath](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation#pushpath10)将info指定的NavDestination页面信息入栈。
*   应用在平板设备上支持单双栏、三分栏布局，组合使用[Navigation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation)组件和[SideBarContainer](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-sidebarcontainer)组件即可实现，更多请参考[一多分栏开发实践](https://gitee.com/harmonyos_samples/multi-columns)。

#### 问题定位

左侧是一个列表组件，点击跳转后右侧显示web页面内容。发现使用的是router跳转且每次跳转的都是同一个页面url。

第一次点击跳转时，有页面跳转日志：

\[(100000:100000:scope)\] Click accepted, tag: Row
\[(100000:100000:scope)\] Page router manager is creating page\[7\]: url: pages/ArtContentPage path: pages/ArtContentPage.js, recoverable: yes, namedRouter: no
\[(100000:100000:scope)\] build ohmUrl for forward compatibility

第二次点击时，没有页面跳转的日志：

\[(100000:100000:scope)\] Click try accept
\[(100000:100000:scope)\] Click accepted, tag: Row
\[(100000:100000:scope)\] Move page to front to index: 1

需要查看代码是否使用了[MOVE\_TO\_TOP\_SINGLETON模式](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation#launchmode12枚举说明)，这个模式下，从栈底向栈顶查找，如果指定的名称已经存在，则将对应的NavDestination页面移到栈顶，不会触发onShown事件。

interface MyParam {
  content?: string
}

@Entry
@Component
export struct Index {
  pathStack: NavPathStack = new NavPathStack()
  @State content: string = 'content1'; _// 传递给子页的参数_

  @Builder
  pageMap(name: string) {
    if (name === "TestPage1") {
      TestPage1();
    }
  }

  build() {
    Navigation(this.pathStack) {
      Column({ space: 24 }) {
        Button('单例跳转子页')
          .onClick(() => {
            _// 单例_
            this.pathStack.pushPath({ name: 'TestPage1', param: { content: this.content } as MyParam },
              { launchMode: LaunchMode.MOVE\_TO\_TOP\_SINGLETON, animated: true })
          })

        Button('改变入参')
          .onClick(() => {
            this.content = 'content2'
          })
      }.width('100%').height('100%').justifyContent(FlexAlign.Center)
    }.navBarWidth('35%')
    .mode(NavigationMode.Split)
    .navDestination(this.pageMap)
    .hideTitleBar(true)
  }
}

@Component
struct TestPage1 {
  navPathStack: NavPathStack = new NavPathStack()
  @State content: string = '';

  build() {
    NavDestination() {
      Stack({ alignContent: Alignment.Center }) {
        Text(this.content).fontSize(20).fontColor(Color.Red)
      }.width('100%').height('100%')
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Blue)
    .onReady((ctx: NavDestinationContext) => {
      this.navPathStack = ctx.pathStack
    })
    .onShown(() => {
      _// 子页从隐藏到显示会触发回调，可用于接收参数_
      this.onPageShow()
    })
  }

  onPageShow(): void {
    const params: ESObject\[\] = this.navPathStack.getParamByName('TestPage1');
    if (params.length > 0) {
      let myParam = params\[params.length - 1\] as MyParam;
      let content = myParam?.content || '';
      this.content = content
    }
  }
}

#### 分析结论

设置了单实例页面模式，由于web页面名称相同，导致页面未重新加载，内容未更新。

#### 修改建议

使用onNewParam回调获取POP\_TO\_SINGLETON跳转传递的参数并刷新页面。具体代码参考：

interface MyParam {
  content?: string
}

@Entry
@Component
export struct Index {
  pathStack: NavPathStack = new NavPathStack()
  @State content: string = 'content1'; _// 传递给子页的参数_

  @Builder
  pageMap(name: string) {
    if (name === "TestPage1") {
      TestPage1();
    }
  }

  build() {
    Navigation(this.pathStack) {
      Column({ space: 24 }) {
        Button('单例跳转子页')
          .onClick(() => {
          _  // 单例_
            this.pathStack.pushPath({ name: 'TestPage1', param: { content: this.content } as MyParam },
              { launchMode: LaunchMode.MOVE\_TO\_TOP\_SINGLETON, animated: true })
          })

        Button('改变入参')
          .onClick(() => {
            this.content = 'content2'
          })
      }.width('100%').height('100%').justifyContent(FlexAlign.Center)
    }.navBarWidth('35%')
    .mode(NavigationMode.Split)
    .navDestination(this.pageMap)
    .hideTitleBar(true)
  }
}

@Component
struct TestPage1 {
  navPathStack: NavPathStack = new NavPathStack()
  @State content: string = '';

  build() {
    NavDestination() {
      Stack({ alignContent: Alignment.Center }) {
        Text(this.content).fontSize(20).fontColor(Color.Red)
      }.width('100%').height('100%')
    }
    .height('100%')
    .width('100%')
    .backgroundColor(Color.Blue)
    .onReady((ctx: NavDestinationContext) => {
      this.navPathStack = ctx.pathStack
    })
    .onShown(() => {
     _ // 子页从隐藏到显示会触发回调，可用于接收参数_
      this.onPageShow()
    })
    .onNewParam((info: ESObject) => {
      _// 若页面就在栈顶，跳转页面不会有页面隐藏到显示的过程，不会触发onShown回调_
      _// 可以在onNewParam中获取新的参数_
      console.info(\`onNewParam： ${JSON.stringify(info)}\`)
      this.content = info.content
    })
  }

  onPageShow(): void {
    const params: ESObject\[\] = this.navPathStack.getParamByName('TestPage1');
    if (params.length > 0) {
      let myParam = params\[params.length - 1\] as MyParam;
      let content = myParam?.content || '';
      this.content = content
    }
  }
}