页面路由指在应用程序中实现不同页面之间的跳转和数据传递。

HarmonyOS提供了Router模块,通过不同的url地址,可以方便地进行页面路由,轻松地访问不同的页面。

包的使用及引用

import router from '@ohos.router'

  1. pushUrl-压栈跳转
pushUrl(options: RouterOptions): Promise<void>

场景: 如果我们从列表页跳转到详情页查看详情,点击返回还要继续查看列表页,可以使用pushUrl,打开详情页的同时,保留了列表页在栈中。

接下来测试一下:

(1)建立两个Page,HmList和HmDetail,如图所示。

(2)实现HmList的布局,代码如下。

class ListItemInfo {

  title: string = ""

  id: number = 0

}

 

@Entry

@Component

struct HmList {

  @State list: ListItemInfo[] = Array.from(Array(100), (_: number, index: number) => {

    return {

      title: `我是第${index + 1}个`,

      id: index + 1

    } as ListItemInfo

  })

  build() {

    Column({ space: 20 }) {

      Row() {

        Text("列表数据")

          .textAlign(TextAlign.Center)

          .width('100%')

          .height(40)

      } .border({

        color: '#f3f4f5',

        width: {

          bottom: 1

        }

      })

      List({ space: 10 }) {

        ForEach(this.list, (item: ListItemInfo) => {

          ListItem () {

            Row() {

              Text(item.title)

              Button("查看详情")

                .height(30)

            }.width('100%')

            .justifyContent(FlexAlign.SpaceBetween)

            .padding({

              left: 10,

              right: 10

            })

          }

        })

      }

    }

  }

}

 

实现效果,如图所示。

(3)实现HmDetail布局,代码如下:

@Entry

@Component

struct HmDetail {

 

  build() {

    Column() {

      Row() {

        Text("详情页")

          .width('100%')

          .textAlign(TextAlign.Center)

      }.height(40)

      .border({

        color: '#f3f4f5',

        width: {

          bottom: 1

        }

      })

 

      Column(){

        Text("详情页")

          .fontSize(50)

      }

      .layoutWeight(1)

      .justifyContent(FlexAlign.Center)

    }

    .height('100%')

  }

}

 

实现效果,如图所示。

(4)在HmList中导入router包,完成路由跳转

import router from '@ohos.router'

Button("查看详情").onClick(() => {

    router.pushUrl({ url: 'pages/HmDetail' })

})

完整代码如下:

import router from '@ohos.router'

 

class ListItemInfo {

  title: string = ""

  id: number = 0

}

 

@Entry

@Component

struct HmList {

  @State list: ListItemInfo[] = Array.from(Array(100), (_: number, index: number) => {

    return {

      title: `我是第${index + 1}个`,

      id: index + 1

    } as ListItemInfo

  })

  build() {

    Column({ space: 20 }) {

      Row() {

        Text("列表数据")

          .textAlign(TextAlign.Center)

          .width('100%')

          .height(40)

      } .border({

        color: '#f3f4f5',

        width: {

          bottom: 1

        }

      })

      List({ space: 10 }) {

        ForEach(this.list, (item: ListItemInfo) => {

          ListItem () {

            Row() {

              Text(item.title)

              Button("查看详情").onClick(() => {

                router.pushUrl({ url: 'pages/HmDetail' })

              })

                .height(30)

            }.width('100%')

            .justifyContent(FlexAlign.SpaceBetween)

            .padding({

              left: 10,

              right: 10

            })

          }

        })

      }

    }

  }

}

  1. replaceUrl-替换跳转

有一个登录页(Login)和一个个人中心页(Profile),希望从登录页成功登录后,跳转到个人中心页。同时,销毁登录页,在返回时直接退出应用。

此时直接replaceUrl方法会在跳转的同时,销毁登录页,在上面的例子中,直接将pushUrl换成replaceUrl即可。

import router from '@ohos.router';



Button("查看详情").onClick(() => {

  router.replaceUrl({ url: 'pages/HmDetail' })

  })

})

总结

(1)当你需要跳转之后,还可以回到上一个页面,使用pushUrl,它会保留当前的页面,压一个新的页面

(2)当你跳转之后,上一个页面的任务已经完成,不需要返回,就可以使用replaceUrl

  1. back返回

router.back() . 返回上一个页面,此时不需要参数,如果说你想要返回的时候带一些参数,需要params和url- 想要指定url.

(1)router.back()

在详情页加一个返回按钮,点击按钮调用router.back()。

import router from '@ohos.router'

Button("返回列表页")

   .onClick(() => {

      router.back()

})

添加一个返回按钮,完整代码如下:

 import router from '@ohos.router'

@Entry

@Component

struct HmDetail {

 

  build() {

    Column() {

      Row() {

        Text("详情页")

          .width('100%')

          .textAlign(TextAlign.Center)

      }.height(40)

      .border({

        color: '#f3f4f5',

        width: {

          bottom: 1

        }

      })

 

      Column(){

        Text("详情页")

          .fontSize(50)

        Button("返回列表页")

          .onClick(() => {

            router.back()

          })

      }

      .layoutWeight(1)

      .justifyContent(FlexAlign.Center)

    }

    .height('100%')

  }

}

 

实现效果,如图所示。

  1. 路由参数

如果需要在跳转时,传递一些数据给目标页,比如列表页到详情页,想把id传过去,就可以使用路由传参的模式。

(1)修改HmList.ets文件,代码如下:

Button("查看详情").onClick(() => {

      router.pushUrl({

          url: 'pages/HmDetail',

              params: {

                    id: item.id

              }

           })

       })

(2)修改HmDetail.ets文件,子组件接收参数,代码如下:

import router from '@ohos.router'

 

class RouterParams {

  id: number = 0

}

 

@Entry

@Component

struct HmDetail {

 

  @State

  detailId: number = 0

  aboutToAppear() {

    const params = router.getParams() as RouterParams

    if(params?.id) {

      this.detailId = params?.id

    }

  }

 

  build() {

    Column() {

      Row() {

        Text("详情页")

          .width('100%')

          .textAlign(TextAlign.Center)

      }.height(40)

      .border({

        color: '#f3f4f5',

        width: {

          bottom: 1

        }

      })

 

      Column(){

        Text("详情页" + this.detailId)

          .fontSize(50)

        Button("返回列表页")

          .onClick(() => {

            router.back()

          })

      }

      .layoutWeight(1)

      .justifyContent(FlexAlign.Center)

    }

    .height('100%')

  }

}

实现效果,如图所示。

->

router.back() 同样可以传递参数给上一级的路由,上一级路由应该在onPageShow里面接收详情页面返回传参。

(1)HmDetail.ets文件,详情组件添加“返回列表页带参数”按钮,代码如下:

  Button("返回列表页带参数")

         .onClick(() => {

           router.back({

             url: 'pages/HmList',

             params: {

               backId: this.detailId

             }

           })

         })

(2)父组件接受参数,HmList.ets文件,代码如下:

class BackRouterParams {

  backId: number = 0

}

onPageShow() {

   const params = router.getParams() as BackRouterParams

    if(params?.backId) {

      AlertDialog.show({

        message: params.backId.toString()

      })

    }

  }

完整代码如下:

import router from '@ohos.router'

 

class ListItemInfo {

  title: string = ""

  id: number = 0

}

 

class BackRouterParams {

  backId: number = 0

}

 

 

@Entry

@Component

struct HmList {

  @State list: ListItemInfo[] = Array.from(Array(100), (_: number, index: number) => {

    return {

      title: `我是第${index + 1}个`,

      id: index + 1

    } as ListItemInfo

  })

  onPageShow() {

    const params = router.getParams() as BackRouterParams

    if(params?.backId) {

      AlertDialog.show({

        message: params.backId.toString()

      })

    }

  }

  build() {

    Column({ space: 20 }) {

      Row() {

        Text("列表数据")

          .textAlign(TextAlign.Center)

          .width('100%')

          .height(40)

      } .border({

        color: '#f3f4f5',

        width: {

          bottom: 1

        }

      })

      List({ space: 10 }) {

        ForEach(this.list, (item: ListItemInfo) => {

          ListItem () {

            Row() {

              Text(item.title)

              Button("查看详情").onClick(() => {

                // router.pushUrl({ url: 'pages/HmDetail' })

                // router.replaceUrl({ url: 'pages/HmDetail' })

                router.pushUrl({

                  url: 'pages/HmDetail',

                  params: {

                    id: item.id

                  }

                })

              })

                .height(30)

            }.width('100%')

            .justifyContent(FlexAlign.SpaceBetween)

            .padding({

              left: 10,

              right: 10

            })

          }

        })

      }

    }

  }

}

 

实现效果,如图所示。

->

总结:

(1)传参用params对象,里面可以传任意内容,key/value由开发者自己定义。

(2)接收端采用router.getParams()获取对象,需要通过class来定义参数的结构,接收之后通过类型断言as指定为具体类型。

(3)如果是通过pushUrl的方式跳转的,返回上一个页面时,aboutToAppear不会执行,需要使用onPageShow来监听当前页面的显示钩子函数。

  1. 路由模式

Standard:标准实例模式,也是默认情况下的实例模式。每次调用该方法都会新建一个目标页,并压入栈顶。

Single:单实例模式。即如果目标页的url在页面栈中已经存在同url页面,则离栈顶最近的同url页面会被移动到栈顶,并重新加载;如果目标页的url在页面栈中不存在同url页面,则按照标准模式跳转。

简单理解一下就是:

(1)Standard-只要push,页面栈里面就会加一项,不管之前加没加过。

(2)Single- 之前加过,不会加新的页面,会把之前加过的页面加出来。

测试- 在detail页面再push到list页,分别使用单例模式和标准模式测试。

  Button("标准模式")

         .onClick(() => {

           router.pushUrl({

             url: 'pages/HmList'

           })

         })

       Button("单例模式")

         .onClick(() => {

           router.pushUrl({

             url: 'pages/HmList'

           }, router.RouterMode.Single)

         })

这里会发现 使用single模式路由返回时的list已经不存在了,因为单例模式只要存在不会再压栈。

HmDetail.ets文件,完整代码如下:

import router from '@ohos.router'

 

class RouterParams {

  id: number = 0

}

 

@Entry

@Component

struct HmDetail {

 

  @State

  detailId: number = 0

  aboutToAppear() {

    const params = router.getParams() as RouterParams

    if(params?.id) {

      this.detailId = params?.id

    }

  }

 

  build() {

    Column() {

      Row() {

        Text("详情页")

          .width('100%')

          .textAlign(TextAlign.Center)

      }.height(40)

      .border({

        color: '#f3f4f5',

        width: {

          bottom: 1

        }

      })

 

      Column(){

        Text("详情页" + this.detailId)

          .fontSize(50)

        Button("返回列表页")

          .onClick(() => {

            router.back()

          })

        Button("返回列表页带参数")

          .onClick(() => {

            router.back({

              url: 'pages/HmList',

              params: {

                backId: this.detailId

              }

            })

          })

        Button("标准模式")

          .onClick(() => {

            router.pushUrl({

              url: 'pages/HmList'

            })

          })

        Button("单例模式")

          .onClick(() => {

            router.pushUrl({

              url: 'pages/HmList'

            }, router.RouterMode.Single)

          })

 

      }

      .layoutWeight(1)

      .justifyContent(FlexAlign.Center)

    }

    .height('100%')

  }

}

实现效果,如图所示。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐