新版vuerouter的hooks用法

31次阅读

共计 2505 个字符,预计需要花费 7 分钟才能阅读完成。

虽然 Vue 3 还没有正式发布,但是热爱新技术的我早已按捺不住自己的内心,开始尝试在小项目中使用它了。

根据这篇《今日凌晨 Vue3 beta 版震撼发布,竟然公开支持脚手架项目!》我搭建了一个 Vue 3 的脚手架项目,用这种方式搭建的脚手架项目不仅仅只有 vue 是新版的,就连 vue-router、vuex 都是最新的。

给大家截一下 package.json 的图:


可以看到 vue-router 和 vuex 都已经开启 4.0 时代啦!

不过其实我并没有去了解过 vue-router 4.0 的新用法什么的,因为我觉得它不像 vue 3.0 都已经进行到 beta 的版本不会有特别大的变动。

而 vue-router 4.0 还是 alpha 的阶段,所以我认为现在去学习它有些为时尚早。但却就是它!差点酿成了一场惨剧。

旧版 vue + vue-router 的使用方式

假如你在路由里面定义了一个动态参数通常都会这么写:

{path: '/:id'}

然后用编程式导航的时候通常会这样去写:

this.$router.push('/123')

在组件中是这样获取这个参数的:

this.$route.params.id

我以为的新版 vue + vue-router 的使用方式

由于 vue 3.0 的 Composition API 中没有 this 了,所以我想到了通过获取组件实例的方式来获取 $route:

import {defineComponent, getCurrentInstance} from 'vue'

export default defineComponent((props, context) => {const { ctx} = getCurrentInstance()
    
    console.log(ctx.$route)
})

没想到打印出来的居然是 undefined!
这是咋回事呢?
于是我又打印了一遍 ctx(ctx 是当前组件上下文 ):


没有 $ 的那些字段是我在组件中自己定义的变量,带 $ 的这些就是 vue 内置的了,找了半天发现没有 $route 了,只剩下了一个 $router,估计 vue-router 4.0 把当前路由信息都转移到 $router 里面去了。

带着猜想,我点开了 $router:


currentRoute! 看名字的话感觉应该就是它了!于是乎我:

import {defineComponent, getCurrentInstance} from 'vue'

export default defineComponent((props, context) => {const { ctx} = getCurrentInstance()
    
    console.log(ctx.$router.currentRoute.value.params.id)
})

果然获取到了!好开心!

实际的新版 vue + vue-router 用法

在接下来的过程中我用 ctx.$router 代替了原来的 this.$router、用 ctx.$router.currentRoute.value 代替了原先的 this.$route。

尽管在接下来的进度中并没有出现任何的 bug,程序一直都是按照我所设想的那样去运行的。

但在项目打包后却出现了意想不到的 bug:在跳转路由的时候报了一个在 undefined 上面没有 push 的错误。

奇了怪了,在开发阶段程序都没有任何的报错怎么一打包就不行了呢?根据我多年的开发经验,我很快就定位到了是 vue-router 的错误。

难道这样写是错的吗?可是我打印了 ctx,它里面明明有一个 $router、$router 里面明明就有 currentRoute、currentRoute 里面明明就有一个 value、value 里面明明就有 params、params 里面我一点开明明就看到了传过来的参数啊:


估计可能是 vue-router 的 bug,果然 alpha 阶段的产物不靠谱,我开始后悔使用新版的 vue 脚手架项目了。

vue-router 里的 hooks

不过这时我突然灵光一现,vue 3 不是受到了 react hooks 的启发才产生了 Composition API 的吗?

那么估计 vue-router 肯定也会受到 react-router 的启发了!

还好我学过 react,果然技多不压身啊!估计里面肯定是有一个 useXxx,就像这样:

import {useXxx} from 'vue-router'

那么应该是 use 什么呢?按理来说应该会尽量的和以前的 API 保持一定的联系,我猜应该是 useRoute 和 useRouter 吧!

为了验证我的想法,我打开了 node_modules 找到了 vue-router 的源码:

果不其然,在第 2454 和第 2455 行我发现它导出了 useRoute 和 useRouter,那么就是它了:

import {defineComponent} from 'vue'
import {useRoute, useRouter} from 'vue-router'

export default defineComponent(_ => {const route = useRoute()
    const router = useRouter()

    console.log(route.params.id)
    router.push('/xxx/xxx')
})

使用这种方式不但可以成功跳转路由,也同样可以获取到路由传过来的参数,这次再打包试了一下,果然就没有之前的那个报错了。

结语

估计以后的 vue 全家桶要开启全民 hooks 的时代了,在翻看源码的同时我发现他们把一些示例都写在了 vue-router/playground 文件夹下了,在里面我发现了一些有趣的用法。

如果有时间的话我会仔细研究一下然后出一篇更加深入的文章给大家,当然如果已经有小伙伴等不及我出新文章的话可以直接进入 vue-router-next 的 github 地址:

https://github.com/vuejs/vue-router-next

它的示例都放在了 playground 这个文件夹下,期待你们研究明白后出一篇更加深入的文章!

正文完
 0