Skip to content

编程式导航

uni-simple-router 中,你可以使用编程式导航来实现页面的跳转和导航操作。编程式导航通常是通过调用路由实例的方法来实现的。

版本陷阱

  • V3 版本发布起,取消了组件式导航,统一使用编程式导航。
  • 在编程式导航中,无论是通过路由实例的方法还是通过路由对象的方法进行导航,它们都会返回一个 Promise 对象。如果导航成功,Promise 对象将会被解析为 undefined,如果导航失败,Promise 对象将会被拒绝,并带有相应的错误信息

如果您需要进行页面导航,uni-simple-router提供了相应的API来满足您的需求。您可以调用相应的方法并传递相应的参数来完成导航操作。需要注意的是,在非H5端可能存在一些特定的限制和要求。例如,在导航到 原生Tabbar 页面时,必须使用 pushTab 方法进行导航操作。这些限制是由各个平台的特性所决定的,uni-simple-router会根据平台的要求进行相应的处理,以确保导航的正确执行。

使用 路由实例 完成导航

js
import {
  createRouter
} from '@/uni-simple-router'

const router = createRouter({
    platform:process.env.VUE_APP_PLATFORM as platformRule,
    routes:[
      // ...
    ]
})

// 字符串路径
router.push('/users/eduardo')

// 带有路径的对象
router.push({ path: '/users/eduardo' })

// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })

// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })

// 跳转到原生Tabbar
router.pushTab({ name: 'tab1' })

// 关闭所有页面并打开指定页面
router.replaceAll({ name: 'my' })

// 替换当前页面栈并打开新页面
router.replace({ name: 'record' }).then(()=>{
  console.log(`导航完成`)
})

// 返回页面
router.back(1)

使用 选项API 完成导航

ts
/// xxx.vue
<script setup lang="ts">
import { useRouter } from '@/uni-simple-router'; 
const router = useRouter();

function goNav(name:string){
    router.replace({
        name
    })
}
</script>

使用 uni.$Router 完成导航

uni-simple-router在实例化时会将实例挂载到uni.$Router上,这样你就可以在不方便导入实例的地方轻松访问路由器实例。这对于一些特殊场景,比如在nvue页面中使用路由实例,非常方便。通过uni.$Router,你可以直接访问路由器的各种方法和属性,以便进行导航、监听路由事件等操作。

ts
// xxx.nvue 
<script setup lang="ts">

import { watch } from 'vue'

const router = uni.$Router
const route = uni.$Route

watch(route,(value)=>{
  console.log(value)
})

router.push({name: `my`})

console.log(route.value)

</script>

温馨提示

  • Vue 实例中,你可以通过 $Router 访问路由实例。因此你可以调用 this.$Router.push
  • Vue 实例中,你同样可以通过 $Route 访问路由元信息,因此你可以调用 this.$Route.query 获取参数。

假设现在你准备跳转到一个新的子路由页面时,以下是可能发生的情况。

假设我们的路由表关系如下:

js
import {
    __dynamicImportComponent__
} from '@/uni-simple-router'

const routes = [
  {
    path: '/admin',
    component: __dynamicImportComponent__(`@/pages/AdminLayout.vue`,{
      pageType:`top`,
    }),
    children: [
      {
        path: 'dashboard/:id',
        name:`dashboard`,
        component: __dynamicImportComponent__(`@/pages/DashboardPage.vue`)
      },
    ]
  },
  {
    path: '/notify',
    component: __dynamicImportComponent__(`@/pages/NotifyLayout.vue`,{
      pageType:`top`,
    }),
    children: [
      {
        path: 'type/:id',
        name:`notifyType`,
        component: __dynamicImportComponent__(`@/pages/NotifyTypePage.vue`)
      },
    ]
  }
];
  1. 假设你当前位置在 /admin 下,准备跳转到 namedashboard 的子路由页面。在导航发生变化时,页面不会出现切屏动画,而是在当前页面下直接更新视图。这是通过 <simple-router-view> 组件挂载 DashboardPage.vue 组件实现的。同时,父级组件执行 updated 的生命周期钩子函数,DashboardPage.vue 组件也执行对应的挂载生命周期钩子函数。此外,$Route 对象的路由元信息也会响应式地发生变化。
  2. 假设你当前位置在 /admin 下,准备跳转到 namenotifyType 的子路由页面。在导航发生变化时,页面将出现切屏动画,并创建一个新的 WebView 来渲染 NotifyLayout.vueNotifyTypePage.vue 组件。同时,$Route 对象的路由元信息也会响应式地发生变化。

综上所述,根据你所在位置的不同,导航行为也会有所不同。如果你所在的位置是根组件(顶级页面)于目标根组件(顶级页面)相同,则会直接在当前页面下更新视图;否则会创建新的 WebView 来渲染页面。

陷阱提示

  • 如果你在非 H5端(例如小程序或App端)执行子路由之间的跳转,创建的页面栈不会影响真机物理返回按键的逻辑。这意味着当你在子路由页面中进行跳转时,无论跳转到多少子路由页面,按下真机物理返回按键时,会直接返回到父级页面或根页面,而不会逐级返回到之前的子路由页面。

router.push

push 方法在功能上与 uni.navigateTo 相同,它们实现了完全一致的效果。这个方法会向 history 栈添加一个新的记录,保留当前页面。uni.navigateTo 支持通过 events 参数进行页面间的通信,但在uni-simple-router中,导航API取消了 events 参数的使用,并采用了另一种组件之间的通信方式。如果你需要详细了解,请参考组件之间的通信方式文档。

ts
/// xxx.vue
<script setup lang="ts">

import { useRouter,parserInstance } from '@/uni-simple-router'; 
const router = useRouter();

router.push({name:`newPage`})
.then(()=>{
  //导航成功,传递通讯数据
  parserInstance(`newPage`,[
    (instance)=>instance.newPageNotify(`来自星星的它`)
  ])
})

</script>

router.pushTab

pushTab 方法在功能上与 uni.switchTab 相同,它们实现了完全一致的效果。这个方法会将所有非原生Tabbar页面都关闭,然后跳转到指定TabBar页面。如果你需要组件与组件间通讯,请参考组件之间的通信方式文档。

ts
/// xxx.vue
<script setup lang="ts">

import { useRouter,parserInstance } from '@/uni-simple-router'; 
const router = useRouter();

router.pushTab({name:`newTab`})
.then(()=>{
  //导航成功,传递通讯数据
  parserInstance(`newTab`,[
    (instance)=>instance.newPageNotify(`来自星星的它`)
  ])
})

</script>

router.replace

replace 方法在功能上与 uni.redirectTo 相同,它们实现了完全一致的效果。这个方法会关闭当前页面,跳转到应用内的某个页面。如果你需要组件与组件间通讯,请参考组件之间的通信方式文档。

ts
/// xxx.vue
<script setup lang="ts">

import { useRouter } from '@/uni-simple-router'; 
const router = useRouter();

router.replace({name:`otherPage`})

</script>

router.replaceAll

replaceAll 方法在功能上与 uni.reLaunch 相同,它们实现了完全一致的效果。这个方法会关闭所有页面,打开到应用内的某个页面。

ts
/// xxx.vue
<script setup lang="ts">

import { useRouter } from '@/uni-simple-router'; 
const router = useRouter();

router.replaceAll({name:`home`})

</script>

router.back

back 方法在功能上与 uni.navigateBack 相同,它们实现了完全一致的效果。这个方法会关闭当前页面,返回上一页面或多级页面。如果你需要组件与组件间通讯,请参考组件之间的通信方式文档。

ts
/// xxx.vue
<script setup lang="ts">

import { useRouter } from '@/uni-simple-router'; 
const router = useRouter();

// 返回一层
router.back(1)

// 返回多层
router.back(2)

// 如果 history 记录不够用,那就默默地失败呗
router.back(100)catch(e=>{
  console.log(e)
})

</script>

uni-app原生方法

除了使用uni-simple-router提供的导航API,如果你仍然喜欢使用uni-app原生的导航方法,uni-simple-router也提供了这个功能。它在底层桥接了uni-app的原生导航方法,因此你可以传递原生导航方法的所有参数,并且可以在使用原生方法时传递与uni-simple-router导航相同的参数。但是需要注意,使用uni-app原生方法可能存在一些缺点:

  1. uni-app原生方法只能用于跳转到顶级页面,无法直接跳转到嵌套子页面中。
  2. uni-app原生方法无法直接跳转动态路由匹配的页面。
  3. 使用复杂的URL字符串传参可能会使代码更加复杂和难以维护。

综上所述,虽然uni-simple-router提供了对uni-app原生导航方法的支持,但建议尽量使用uni-simple-router提供的导航API,以获得更好的路由管理和参数传递的体验。

一个简单的列子:

js
import {
    __dynamicImportComponent__
} from '@/uni-simple-router'

const routes = [
  {
    path: '/admin',
    component: __dynamicImportComponent__(`@/pages/AdminLayout.vue`,{
      pageType:`top`,
    }),
    children: [
      {
        path: 'dashboard/:id',
        name:`dashboard`,
        component: __dynamicImportComponent__(`@/pages/DashboardPage.vue`)
      },
    ]
  }
];

假设现在的路由关系为嵌套路由,我们使用不同的方式跳转,请关注下方的代码:

js
// 原生方法
uni.navigateTo({
  url:`/pages/AdminLayout?name=hhyang`
})
// 或者使用如下:
uni.navigateTo({
  path:`/admin`,
  query:{
    name:`hhyang`
  }
})

// 假如你正在vue组件内部,你可以直接访问 $Router
this.$Router.push(`/admin?name=hhyang`)

// 跳转到嵌套动态路由
uni.navigateTo({
  path:`/admin/dashboard/123`,
})
// 或者
this.$Router.push({
  name:`dashboard`,
  params:{
    id:123
  }
})
编程式导航 has loaded