Skip to content

页面路由

HarmonyOS 提供两种页面路由方案:

方案版本适用场景
Navigation + NavPathStackAPI 10+官方推荐,支持复杂导航、转场动画
@ohos.routerAPI 9+简单页面跳转,已不推荐新项目使用

创建新页面

typescript
// entry/src/main/ets/pages/DetailPage.ets
@Component
export struct DetailPage {
  @Prop id: string = ''
  @Prop title: string = ''

  build() {
    Column() {
      Text(`详情页`)
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin(20)

      Text(`ID: ${this.id}`)
        .fontSize(16)
        .margin(10)

      Text(`标题: ${this.title}`)
        .fontSize(16)
        .margin(10)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

入口页配置 Navigation

typescript
// entry/src/main/ets/pages/Index.ets
import { DetailPage } from './DetailPage'

@Entry
@Component
struct Index {
  // 创建导航栈
  pathStack: NavPathStack = new NavPathStack()

  // 页面映射表
  @Builder
  pageMap(name: string) {
    if (name === 'detail') {
      DetailPage()
    }
  }

  build() {
    Navigation(this.pathStack) {
      Column({ space: 20 }) {
        Text('首页')
          .fontSize(24)
          .fontWeight(FontWeight.Bold)

        Button('打开详情页(带参数)')
          .onClick(() => {
            this.pathStack.pushPath({
              name: 'detail',
              params: {
                id: '42',
                title: '示例标题'
              }
            })
          })

        Button('打开详情页(无参数)')
          .onClick(() => {
            this.pathStack.pushPath({ name: 'detail' })
          })
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
    }
    .navDestination(this.pageMap)
    .mode(NavigationMode.Stack)
    .hideTitleBar(false)
    .title('我的应用')
  }
}

在详情页获取参数

typescript
@Component
export struct DetailPage {
  @State id: string = ''
  @State title: string = ''

  aboutToAppear() {
    // 通过 NavDestination 获取参数
    const params = this.getUIContext().getRouter().getParams() as Record<string, string>
    if (params) {
      this.id = params['id'] || ''
      this.title = params['title'] || ''
    }
  }

  build() {
    Column() {
      // ...
      Button('返回')
        .onClick(() => {
          // 返回上一页
          this.getUIContext().getRouter().back()
        })
    }
  }
}

导航栈操作

typescript
// 跳转到新页面
this.pathStack.pushPath({ name: 'detail', params: {} })

// 返回上一页
this.pathStack.pop()

// 返回到指定页面
this.pathStack.popToName('home')

// 清空栈并跳转
this.pathStack.clear()
this.pathStack.pushPath({ name: 'login' })

// 替换当前页面
this.pathStack.replacePath({ name: 'newPage' })

// 获取栈深度
const depth = this.pathStack.size()

// 获取当前页面参数
const params = this.pathStack.getParamByIndex(0)

@ohos.router 方案(旧)

注意

此方案已不推荐新项目使用,仅作了解。

配置路由表

json
// resources/base/profile/main_pages.json
{
  "src": [
    "pages/Index",
    "pages/DetailPage"
  ]
}

页面跳转

typescript
import router from '@ohos.router'

// 跳转页面
router.pushUrl({
  url: 'pages/DetailPage',
  params: { id: '42' }
})

// 返回
router.back()

// 获取参数
const params = router.getParams() as Record<string, string>

页面传参对比

方式Navigation@ohos.router
路由表配置代码中 navDestinationmain_pages.json
传参params 对象params 对象
取参getUIContext().getRouter().getParams()router.getParams()
返回back()back()
栈操作丰富(pop/popToName/clear)简单

完整示例:带底部导航的应用

typescript
@Entry
@Component
struct MainPage {
  @State currentIndex: number = 0
  pathStack: NavPathStack = new NavPathStack()

  @Builder
  tabBuilder(title: string, index: number, selectedIcon: Resource, normalIcon: Resource) {
    Column() {
      Image(this.currentIndex === index ? selectedIcon : normalIcon)
        .width(24)
        .height(24)
      Text(title)
        .fontSize(12)
        .fontColor(this.currentIndex === index ? '#007DFF' : '#999999')
    }
    .onClick(() => {
      this.currentIndex = index
    })
  }

  build() {
    Navigation(this.pathStack) {
      Tabs({ barPosition: BarPosition.End }) {
        TabContent() {
          HomeTab()
        }
        .tabBar(this.tabBuilder('首页', 0, $r('app.media.home_selected'), $r('app.media.home')))

        TabContent() {
          DiscoverTab()
        }
        .tabBar(this.tabBuilder('发现', 1, $r('app.media.discover_selected'), $r('app.media.discover')))

        TabContent() {
          ProfileTab()
        }
        .tabBar(this.tabBuilder('我的', 2, $r('app.media.profile_selected'), $r('app.media.profile')))
      }
    }
    .hideTitleBar(true)
  }
}