Vue Router and the Composition API

Watch a free video lesson on Vue School

The introduction of setup and Vue’s Composition API, open up new possibilities but to be able to get the full potential out of Vue Router, we will need to use a few new functions to replace access to this and in-component navigation guards.

Accessing the Router and current Route inside setup

Because we don’t have access to this inside of setup, we cannot directly access this.$router or this.$route anymore. Instead we use the useRouter function:

  1. import { useRouter, useRoute } from 'vue-router'
  2. export default {
  3. setup() {
  4. const router = useRouter()
  5. const route = useRoute()
  6. function pushWithQuery(query) {
  7. router.push({
  8. name: 'search',
  9. query: {
  10. ...route.query,
  11. },
  12. })
  13. }
  14. },
  15. }

The route object is a reactive object, so any of its properties can be watched and you should avoid watching the whole route object. In most scenarios, you should directly watch the param you are expecting to change

  1. import { useRoute } from 'vue-router'
  2. import { ref } from 'vue'
  3. export default {
  4. setup() {
  5. const route = useRoute()
  6. const userData = ref()
  7. // fetch the user information when params change
  8. watch(
  9. () => route.params.id,
  10. async newId => {
  11. userData.value = await fetchUser(newId)
  12. }
  13. )
  14. },
  15. }

Note we still have access to $router and $route in templates, so there is no need to return router or route inside of setup.

Navigation Guards

While you can still use in-component navigation guards with a setup function, Vue Router exposes update and leave guards as Composition API functions:

  1. import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
  2. import { ref } from 'vue'
  3. export default {
  4. setup() {
  5. // same as beforeRouteLeave option with no access to `this`
  6. onBeforeRouteLeave((to, from) => {
  7. const answer = window.confirm(
  8. 'Do you really want to leave? you have unsaved changes!'
  9. )
  10. // cancel the navigation and stay on the same page
  11. if (!answer) return false
  12. })
  13. const userData = ref()
  14. // same as beforeRouteUpdate option with no access to `this`
  15. onBeforeRouteUpdate(async (to, from) => {
  16. // only fetch the user if the id changed as maybe only the query or the hash changed
  17. if (to.params.id !== from.params.id) {
  18. userData.value = await fetchUser(to.params.id)
  19. }
  20. })
  21. },
  22. }

Composition API guards can also be used in any component rendered by <router-view>, they don’t have to be used directly on the route component like in-component guards.

useLink

Vue Router exposes the internal behavior of RouterLink as a Composition API function. It gives access the same properties as the v-slot API:

  1. import { RouterLink, useLink } from 'vue-router'
  2. import { computed } from 'vue'
  3. export default {
  4. name: 'AppLink',
  5. props: {
  6. // add @ts-ignore if using TypeScript
  7. ...RouterLink.props,
  8. inactiveClass: String,
  9. },
  10. setup(props) {
  11. const { route, href, isActive, isExactActive, navigate } = useLink(props)
  12. const isExternalLink = computed(
  13. () => typeof props.to === 'string' && props.to.startsWith('http')
  14. )
  15. return { isExternalLink, href, navigate, isActive }
  16. },
  17. }