Vue Router

60 phút

Vue Router

Vue Router

Giới thiệu Vue Router

Vue Router là thư viện routing chính thức cho Vue.js.

Cài đặt và Cấu hình

Cài đặt

npm install vue-router@4

Cấu hình Router

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: About
  },
  {
    path: '/user/:id',
    name: 'User',
    component: () => import('../views/User.vue'),
    props: true
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

Kết nối với App

// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')

Router Links và Views

RouterLink

<template>
  <nav>
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-link :to="{ name: 'User', params: { id: 123 } }">
      User Profile
    </router-link>
  </nav>
</template>

RouterView

<template>
  <div id="app">
    <nav>
      <!-- Navigation links -->
    </nav>
    <main>
      <router-view></router-view>
    </main>
  </div>
</template>

Route Parameters và Query

Dynamic Routes

<template>
  <div>
    <h1>User Profile</h1>
    <p>User ID: {{ $route.params.id }}</p>
    <p>Query: {{ $route.query.search }}</p>
  </div>
</template>

<script>
export default {
  created() {
    console.log('User ID:', this.$route.params.id)
  }
}
</script>

Composition API

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

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

const userId = route.params.id
const searchQuery = route.query.search

const goToHome = () => {
  router.push('/')
}

const goToUser = (id) => {
  router.push({ name: 'User', params: { id } })
}
</script>

Navigation Guards

Global Guards

// router/index.js
router.beforeEach((to, from, next) => {
  const isAuthenticated = checkAuth()
  
  if (to.meta.requiresAuth && !isAuthenticated) {
    next('/login')
  } else {
    next()
  }
})

Route-specific Guards

{
  path: '/dashboard',
  component: Dashboard,
  beforeEnter: (to, from, next) => {
    if (!isAdmin()) {
      next('/unauthorized')
    } else {
      next()
    }
  }
}

Component Guards

<script>
export default {
  beforeRouteEnter(to, from, next) {
    // Không thể truy cập this
    next(vm => {
      // Có thể truy cập component instance qua vm
    })
  },
  
  beforeRouteUpdate(to, from, next) {
    // React to route changes
    this.userData = null
    this.fetchUserData(to.params.id)
    next()
  },
  
  beforeRouteLeave(to, from, next) {
    if (this.hasUnsavedChanges) {
      if (confirm('Bạn có chắc muốn rời đi? Thay đổi chưa được lưu sẽ mất.')) {
        next()
      } else {
        next(false)
      }
    } else {
      next()
    }
  }
}
</script>

Nested Routes

Cấu hình Nested Routes

{
  path: '/user/:id',
  component: User,
  children: [
    {
      path: '',
      component: UserProfile
    },
    {
      path: 'posts',
      component: UserPosts
    },
    {
      path: 'settings',
      component: UserSettings
    }
  ]
}

Sử dụng trong Template

<template>
  <div class="user">
    <nav class="user-nav">
      <router-link :to="`/user/${$route.params.id}`">Profile</router-link>
      <router-link :to="`/user/${$route.params.id}/posts`">Posts</router-link>
      <router-link :to="`/user/${$route.params.id}/settings`">Settings</router-link>
    </nav>
    
    <div class="user-content">
      <router-view></router-view>
    </div>
  </div>
</template>

Bài tập 1