跳至内容

Vue 路由器和组合 API

Vue 的 组合 API 的引入开辟了新的可能性,但为了能够充分发挥 Vue 路由器的潜力,我们需要使用一些新函数来替换对 this 的访问以及组件内导航守卫。

setup 中访问路由器和当前路由

因为我们在 setup 中无法访问 this,所以我们不能直接访问 this.$routerthis.$route。相反,我们使用 useRouteruseRoute 组合函数

vue
<script setup>
import { useRouter, useRoute } from 'vue-router'

const router = useRouter()
const route = useRoute()

function pushWithQuery(query) {
  router.push({
    name: 'search',
    query: {
      ...route.query,
      ...query,
    },
  })
}
</script>

route 对象是一个响应式对象。在大多数情况下,你应该避免观察整个 route 对象。相反,你可以直接观察你期望改变的属性

vue
<script setup>
import { useRoute } from 'vue-router'
import { ref, watch } from 'vue'

const route = useRoute()
const userData = ref()

// fetch the user information when params change
watch(
  () => route.params.id,
  async newId => {
    userData.value = await fetchUser(newId)
  }
)
</script>

请注意,我们仍然可以在模板中访问 $router$route,因此如果我们只需要在模板中使用这些对象,则无需使用 useRouteruseRoute

Vue 路由器将更新和离开守卫公开为组合 API 函数

vue
<script setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
import { ref } from 'vue'

// same as beforeRouteLeave option but with no access to `this`
onBeforeRouteLeave((to, from) => {
  const answer = window.confirm(
    'Do you really want to leave? you have unsaved changes!'
  )
  // cancel the navigation and stay on the same page
  if (!answer) return false
})

const userData = ref()

// same as beforeRouteUpdate option but with no access to `this`
onBeforeRouteUpdate(async (to, from) => {
  // only fetch the user if the id changed as maybe only the query or the hash changed
  if (to.params.id !== from.params.id) {
    userData.value = await fetchUser(to.params.id)
  }
})
</script>

组合 API 守卫也可以在 <router-view> 渲染的任何组件中使用,它们不必像组件内守卫那样直接用于路由组件。

Vue 路由器将 RouterLink 的内部行为公开为一个组合函数。它接受一个响应式对象,例如 RouterLink 的道具,并公开低级属性以构建你自己的 RouterLink 组件或生成自定义链接

vue
<script setup>
import { RouterLink, useLink } from 'vue-router'
import { computed } from 'vue'

const props = defineProps({
  // add @ts-ignore if using TypeScript
  ...RouterLink.props,
  inactiveClass: String,
})

const {
  // the resolved route object
  route,
  // the href to use in a link
  href,
  // boolean ref indicating if the link is active
  isActive,
  // boolean ref indicating if the link is exactly active
  isExactActive,
  // function to navigate to the link
  navigate
} = useLink(props)

const isExternalLink = computed(
  () => typeof props.to === 'string' && props.to.startsWith('http')
)
</script>

请注意,RouterLink 的 v-slot 提供与 useLink 组合函数相同的属性。