编程式导航

在前一节的代码中,执行路由切换的操作都是以单击 <router-link> 组件来触发导航操作的,这种方式称作声明式导航。在 vue-router 中除了使用 <router-link> 来定义导航链接外,还可以借助 router 的实例方法通过编写代码来实现,这就是所谓的编程式导航。下面介绍编程式导航的几个常用方法。

router.push(location, onComplete?, onAbort?)

在之前的代码中曾使用过 this.$route.params 获取路由的参数,this.$route 为当前的路由对象,在实现路由切换时,如果使用编程式导航,需要使用 this.$router.push 方法,通过 this.$router 获取的是设置在根实例中的一个 Vue Router 的实例,push 方法是由实例对象提供的,所以不要把 this.$routethis.$router 搞混了。

router.push 方法的第一个参数可以是一个字符串路径,也可以是一个描述地址的对象,在这个对象中可以设置传递到下一个路由的参数。onCompleteonAbort 作为第二个和第三个参数分别接收一个回调函数,它们分别表示当导航成功时触发和导航失败时触发(导航到相同的路由或在当前导航完成之前就导航到另一个不同的路由),不过这两个参数不是必须要传入的,如示例代码7-8-1所示。

示例代码7-8-1 push方法
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 带查询参数,变成 /user?userId=test
router.push({ path: '/user', query: { userId: 'test' }})
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

在上面列出的方法中,在调用 router.push 方法时,第一个参数设置成对象,可以实现导航和传递参数的功能,path 对应路由配置信息中定义的 pathquery 设置传递的参数,在导航后的组件可以使用 this.$route.query 来接收,最后一种使用 name 的方式来表明跳转的路由,params 设置传递的参数,这里的方式为命名路由。

有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由或者执行一些跳转时。在创建 router 实例时,在 routes 配置中给某个路由设置 name 属性,如示例代码7-8-2所示。

示例代码7-8-2 命名路由
var router = new VueRouter({
    routes: [
        {
            path: '/user/:id',
            name: 'user',
            component: User
        }
    ]
})

那么使用 name+paramspath+query 有什么区别呢?总结如下:

  • 进行路由配置时,path 是必配的,而 name 可以选配。

  • 使用 name 或者 path 进行导航时,当传参可以使用 params 时,接收参数使用 $route.parmas;当传参使用 query 时,接收参数使用 $route.query

  • query 的参数一般以 ?xx=xx 形式跟在路径后面。query 类似于 Ajax 中的 get 传参,params 则类似于 post,简单来说,前者在浏览器地址栏中显示参数,后者则不显示。

注意,当采用 name 进行导航时,如果 path 里面有需要的参数,例如 :id,那么对应的 params 也需要传递 id 参数,否则将无法被正确导航,代码如下:

// 对应path:'/user/:id'
this.$router.push({
    name:'user',
    params:{
        id:id // 必须传递id
    }
})

调用 router.push 方法时,会向 history 栈添加一个新的记录,所以,当用户单击浏览器后退按钮时,就会回到之前的 URL。如果这时采用 query 传参,那么页面刷新时参数可以保留,效果如图7-3所示。

image 2024 02 23 16 42 42 228
Figure 1. 图7-3 采用query传参,页面刷新时保留了参数

router.replace(location, onComplete?, onAbort?)

router.replace 方法也可以进行路由切换从而实现导航,与 router.push 很像,唯一不同的是,它不会向 history 添加新记录,而是跟它的方法名一样,替换 (replace) 掉当前的 history 记录。也就是当用户单击浏览器返回时,并不会向 history 添加记录。

router.go(Number)

router.go 方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似于 window.history.go(n),如示例代码7-8-3所示。

示例代码7-8-3 router.go
// 在浏览器记录中前进一步,等同于 router.forward()
router.go(1)
// 后退一步记录,等同于 router.back()
router.go(-1)
// 前进 3 步记录
router.go(3)
// 如果 history 记录不够用,就会失败
router.go(-100)
router.go(100)

router.reslove(location)

router.reslove 方法可以将一个 routerlocation 配置转换成一个标准对象,提供 basehref 属性,例如,如果不想采用 router 调整,可以使用浏览器原生的跳转,如示例代码7-8-4所示。

let routeData = router.resolve({
    path: path,
    query: query || {}
})
window.open(routeData.href);

这样就可以将页面链接的根路径解析出来,而不用写死在代码中,但是如果 path 并不是在 router 中定义的,那么 resolve 方法将会报错。