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"