VueRouter 基础教程系列 🎉
以 CompositionAPI 的方式来使用 VueRouter 首要注意的就是无法在 setup 中通过 this 来访问组件实例。但这并不影响模板与组件实例的绑定关系(含义就是模板中依然可以通过组件实例来访问 $route 与 $router 对象)。
route 与 router
由于 setup 中无法通过 this 来访问组件实例,因此无法直接访问 this.$router 与 this.$route。作为替代,我们使用 useRouter 函数来分别获取路由记录对象 (route) 和 路由器对象 (router)。
const {route, router} = useRouter();
⚠️ 注意,route 对象整个都是响应式的,所以我们要避免监听整个 route 对象,而是监听它的具体属性。
watch(()=>route.params, async newParams=> {
userData.value = await fetchUser(newParams.id)
});
路由导航守卫
VueRouter 提供了 onBeforeRouteUpdate 和 onBeforeRouteLeave 两个组合式函数的导航守卫。
import { defineComponent, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue';
defineComponent({
setup() {
//路径参数发生改变后,重新请求数据。
onBeforeRouteUpdate(async (to, from) => {
if (to.params.id !== from.params.id) {
userData.value = await fetchUser(to.params.id)
}
});
onBeforeRouteLeave((to, from) => {
const answer = window.confirm(
'Do you really want to leave? you have unsaved changes!'
)
// 取消导航并停留在同一页面上
if (!answer) return false
})
}
});
⚠️ 谨记,VueRouter 只提供了这两个组合函数风格的导航守卫,并没有提供 beforeRouteEnter。
当路由仅是路径参数、
query、hash发生改变,而不是path发生改变时,那么路由组件就会被复用,此时便会触发onBeforeRouteUpdate。
useLink
useLink 组合函数公开了 router-link 组件在导航时其内部所产生的行为与信息。这些行为和信息与通过 router-link 作用域插槽 (v-slot) 所接收的属性完全相同。
<router-link v-slot="{route, href, isActive, isExactActive, navigat}">
{{href}}
</router-link>
useLink 函数所接收的参数与 router-link 所接收的 props 完全一致。
就是说可以通过
useLink函数获取router-link跳转时产生的行为与信息,但并不会真实发生跳转行为。
const { route, href, isActive, isExactActive, navigate } = useLink({to:'/'});
我们可以将 useLink 的功能看作是对 router-link 的一次预解析。通过预解析,我们可以对 router-link 再封装,以更丰富的方式来应对我们需求中不同形式的链接的跳转,例如内部链接、外部链接(第三方链接)、是否新窗口打开等。
import { RouterLink, useLink } from 'vue-router'
export default {
name: 'AppLink',
props: {
// 如果使用 TypeScript,请添加 @ts-ignore
...RouterLink.props,
inactiveClass: String,
},
setup(props) {
const { route, href, isActive, isExactActive, navigate } = useLink(props)
const isExternalLink = computed(
() => typeof props.to === 'string' && props.to.startsWith('http')
)
return { isExternalLink, href, navigate, isActive }
},
}
⚠️ 在跳转第三方链接时,为了我们页面的性能与安全,强烈建议为 a 标签设置 rel="noopener"