阿里云主机折上折
  • 微信号
Current Site:Index > Routing Composition API (useRouter/useRoute)

Routing Composition API (useRouter/useRoute)

Author:Chuan Chen 阅读数:45099人阅读 分类: Vue.js

Composition API for Routing (useRouter/useRoute)

Vue Router 4.x provides two Composition APIs: useRouter and useRoute, which make it easier to access the router instance and current route information within the setup function. These APIs replace the this.$router and this.$route from previous versions and are more suitable for use with the Composition API.

Basic Usage of useRouter

useRouter returns the router instance, equivalent to the previous this.$router. It allows us to perform programmatic navigation:

import { useRouter } from 'vue-router'

export default {
  setup() {
    const router = useRouter()
    
    const navigateToHome = () => {
      router.push('/home')
    }
    
    const replaceToAbout = () => {
      router.replace('/about')
    }
    
    const goBack = () => {
      router.go(-1)
    }
    
    return {
      navigateToHome,
      replaceToAbout,
      goBack
    }
  }
}

Basic Usage of useRoute

useRoute returns the current route object, equivalent to the previous this.$route. It contains various information about the current route:

import { useRoute } from 'vue-router'

export default {
  setup() {
    const route = useRoute()
    
    // Access route parameters
    const userId = computed(() => route.params.id)
    
    // Access query parameters
    const searchQuery = computed(() => route.query.q)
    
    // Access hash
    const sectionHash = computed(() => route.hash)
    
    return {
      userId,
      searchQuery,
      sectionHash
    }
  }
}

Comparison Between Composition API and Options API

In the Options API, we typically access the router like this:

export default {
  methods: {
    navigate() {
      this.$router.push('/somewhere')
    }
  },
  computed: {
    currentPath() {
      return this.$route.path
    }
  }
}

In the Composition API, the code is clearer and more flexible:

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

export default {
  setup() {
    const router = useRouter()
    const route = useRoute()
    
    const currentPath = computed(() => route.path)
    
    const navigate = () => {
      router.push('/somewhere')
    }
    
    return {
      currentPath,
      navigate
    }
  }
}

Using Router Outside of setup

Sometimes we need to access the router outside the setup function, such as in utility functions:

// utils/navigation.js
import { useRouter } from 'vue-router'

export function useNavigation() {
  const router = useRouter()
  
  const navigateTo = (path) => {
    router.push(path)
  }
  
  return {
    navigateTo
  }
}

Then use it in a component:

import { useNavigation } from '@/utils/navigation'

export default {
  setup() {
    const { navigateTo } = useNavigation()
    
    const goToAbout = () => {
      navigateTo('/about')
    }
    
    return {
      goToAbout
    }
  }
}

Composition-Style Route Guards

Vue Router 4.x also provides Composition API-style navigation guards:

import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'

export default {
  setup() {
    onBeforeRouteLeave((to, from) => {
      const answer = window.confirm('Are you sure you want to leave?')
      if (!answer) return false
    })
    
    onBeforeRouteUpdate(async (to, from) => {
      // Fetch new data when route parameters change
      await fetchData(to.params.id)
    })
  }
}

Dynamic Route Matching

Using useRoute, dynamic route parameters can be easily handled:

import { useRoute } from 'vue-router'
import { watch } from 'vue'

export default {
  setup() {
    const route = useRoute()
    
    // Perform actions when route parameters change
    watch(
      () => route.params.id,
      (newId) => {
        fetchUserData(newId)
      }
    )
  }
}

Accessing Route Meta Information

The meta field in route configuration can be accessed via useRoute:

import { useRoute } from 'vue-router'
import { computed } from 'vue'

export default {
  setup() {
    const route = useRoute()
    
    const requiresAuth = computed(() => route.meta.requiresAuth)
    const pageTitle = computed(() => route.meta.title || 'Default Title')
    
    return {
      requiresAuth,
      pageTitle
    }
  }
}

Handling Nested Routes

When dealing with nested routes, useRoute provides complete matched route records:

import { useRoute } from 'vue-router'

export default {
  setup() {
    const route = useRoute()
    
    // Get all matched route records
    const matchedRoutes = route.matched
    
    // Find specific meta fields
    const hasAdminAccess = matchedRoutes.some(
      record => record.meta.requiresAdmin
    )
  }
}

Integration with Pinia State Management

Using router Composition APIs in Pinia stores:

// stores/navigation.js
import { defineStore } from 'pinia'
import { useRouter, useRoute } from 'vue-router'

export const useNavigationStore = defineStore('navigation', () => {
  const router = useRouter()
  const route = useRoute()
  
  const currentRouteName = computed(() => route.name)
  
  function navigateTo(routeName) {
    router.push({ name: routeName })
  }
  
  return {
    currentRouteName,
    navigateTo
  }
})

Reactive Route Parameters

Leveraging Vue's reactivity system, you can create reactive states based on route parameters:

import { useRoute } from 'vue-router'
import { ref, watch } from 'vue'

export default {
  setup() {
    const route = useRoute()
    const postId = ref(route.params.id)
    
    watch(
      () => route.params.id,
      (newId) => {
        postId.value = newId
        loadPost(newId)
      }
    )
    
    return {
      postId
    }
  }
}

Route Lazy Loading with Composition API

Combining route lazy loading with Composition API for more efficient code splitting:

import { defineAsyncComponent } from 'vue'

const routes = [
  {
    path: '/dashboard',
    component: defineAsyncComponent(() =>
      import('@/views/Dashboard.vue')
    ),
    meta: { requiresAuth: true }
  }
]

Mocking Routes in Tests

Mocking routes in component tests:

import { mount } from '@vue/test-utils'
import { useRoute, useRouter } from 'vue-router'

jest.mock('vue-router', () => ({
  useRoute: jest.fn(),
  useRouter: jest.fn()
}))

test('Testing route-related functionality', () => {
  useRoute.mockImplementation(() => ({
    params: { id: '123' }
  }))
  
  const push = jest.fn()
  useRouter.mockImplementation(() => ({
    push
  }))
  
  const wrapper = mount(Component)
  
  wrapper.find('button').trigger('click')
  expect(push).toHaveBeenCalledWith('/expected-path')
})

Route Transition Animations

Combining routes with transition animations:

import { useRoute } from 'vue-router'
import { ref, watch } from 'vue'

export default {
  setup() {
    const route = useRoute()
    const transitionName = ref('fade')
    
    watch(
      () => route.meta.transition,
      (newTransition) => {
        transitionName.value = newTransition || 'fade'
      }
    )
    
    return {
      transitionName
    }
  }
}

Scroll Behavior Control

Customizing scroll behavior:

import { useRouter } from 'vue-router'

export default {
  setup() {
    const router = useRouter()
    
    router.options.scrollBehavior = (to, from, savedPosition) => {
      if (savedPosition) {
        return savedPosition
      } else if (to.hash) {
        return { el: to.hash }
      } else {
        return { top: 0 }
      }
    }
  }
}

Route Error Handling

Handling navigation errors:

import { useRouter } from 'vue-router'

export default {
  setup() {
    const router = useRouter()
    
    const navigateSafely = async (path) => {
      try {
        await router.push(path)
      } catch (error) {
        if (error.name === 'NavigationDuplicated') {
          // Handle duplicate navigation error
        } else {
          // Handle other navigation errors
        }
      }
    }
    
    return {
      navigateSafely
    }
  }
}

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.