λ΄λΉκ²μ΄μ κ°λ β
μ΄λ¦μμ μ μ μλ―μ΄, Vue λΌμ°ν°μμ μ 곡νλ λ΄λΉκ²μ΄μ κ°λλ μ£Όλ‘ λ΄λΉκ²μ΄μ μ 리λλ μ νκ±°λ μ·¨μνμ¬ λ΄λΉκ²μ΄μ μ 보νΈνλ λ° μ¬μ©λ©λλ€. λΌμ°νΈ λ΄λΉκ²μ΄μ κ³Όμ μ ν μ κ±°λ λ°©λ²μλ μ μ, λΌμ°νΈλ³, μ»΄ν¬λνΈ λ΄μμ λ± μ¬λ¬ κ°μ§κ° μμ΅λλ€.
μ μ Before κ°λ β
router.beforeEach
λ₯Ό μ¬μ©νμ¬ μ μ before κ°λλ₯Ό λ±λ‘ν μ μμ΅λλ€:
const router = createRouter({ ... })
router.beforeEach((to, from) => {
// ...
// λ΄λΉκ²μ΄μ
μ μ·¨μνλ €λ©΄ λͺ
μμ μΌλ‘ falseλ₯Ό λ°ννμΈμ
return false
})
μ μ before κ°λλ μμ± μμλλ‘, λ΄λΉκ²μ΄μ μ΄ νΈλ¦¬κ±°λ λλ§λ€ νΈμΆλ©λλ€. κ°λλ λΉλκΈ°μ μΌλ‘ ν΄κ²°λ μ μμΌλ©°, λͺ¨λ ν μ΄ ν΄κ²°λκΈ° μ κΉμ§ λ΄λΉκ²μ΄μ μ 보λ₯(pending) μνλ‘ κ°μ£Όλ©λλ€.
λͺ¨λ κ°λ ν¨μλ λ κ°μ μΈμλ₯Ό λ°μ΅λλ€:
to
: μ΄λνλ €λ λμ λΌμ°νΈ μμΉ μ κ·νλ νμfrom
: μ΄λ μ νμ¬ λΌμ°νΈ μμΉ μ κ·νλ νμ
κ·Έλ¦¬κ³ μ νμ μΌλ‘ λ€μ κ° μ€ νλλ₯Ό λ°νν μ μμ΅λλ€:
false
: νμ¬ λ΄λΉκ²μ΄μ μ μ·¨μν©λλ€. λΈλΌμ°μ URLμ΄ λ³κ²½λ κ²½μ°(μ¬μ©μκ° μλμΌλ‘ λ³κ²½νκ±°λ λ€λ‘ κ°κΈ° λ²νΌμ μ¬μ©ν κ²½μ°),from
λΌμ°νΈμ URLλ‘ μ¬μ€μ λ©λλ€.λΌμ°νΈ μμΉ: λΌμ°νΈ μμΉλ₯Ό μ λ¬νμ¬ λ€λ₯Έ μμΉλ‘ 리λλ μ ν©λλ€. μ΄λ
router.push()
λ₯Ό νΈμΆνλ κ²κ³Ό κ°μΌλ©°,replace: true
λname: 'home'
κ³Ό κ°μ μ΅μ μ μ λ¬ν μ μμ΅λλ€. νμ¬ λ΄λΉκ²μ΄μ μ μ€λ¨λκ³ λμΌνfrom
μ κ°μ§ μλ‘μ΄ λ΄λΉκ²μ΄μ μ΄ μμ±λ©λλ€.jsrouter.beforeEach(async (to, from) => { if ( // μ¬μ©μκ° μΈμ¦λμλμ§ νμΈ !isAuthenticated && // βοΈ λ¬΄ν 리λλ μ λ°©μ§ to.name !== 'Login' ) { // μ¬μ©μλ₯Ό λ‘κ·ΈμΈ νμ΄μ§λ‘ 리λλ μ return { name: 'Login' } } })
μμμΉ λͺ»ν μν©μ΄ λ°μν κ²½μ° Error
λ₯Ό throwν μλ μμ΅λλ€. μ΄ κ²½μ°μλ λ΄λΉκ²μ΄μ
μ΄ μ·¨μλκ³ router.onError()
λ₯Ό ν΅ν΄ λ±λ‘λ μ½λ°±μ΄ νΈμΆλ©λλ€.
μ무κ²λ λ°ννμ§ μκ±°λ, undefined
λλ true
λ₯Ό λ°ννλ©΄ λ΄λΉκ²μ΄μ
μ΄ μ ν¨νλ€κ³ κ°μ£Όλμ΄ λ€μ λ΄λΉκ²μ΄μ
κ°λκ° νΈμΆλ©λλ€.
μμ λͺ¨λ λ΄μ©μ async
ν¨μ λ° Promiseμ λμΌνκ² λμν©λλ€:
router.beforeEach(async (to, from) => {
// canUserAccess()λ `true` λλ `false`λ₯Ό λ°ν
const canAccess = await canUserAccess(to)
if (!canAccess) return '/login'
})
μ νμ μΈ λ²μ§Έ μΈμ next
β
μ΄μ λ²μ μ Vue Routerμμλ μΈ λ²μ§Έ μΈμ next
λ₯Ό μ¬μ©ν μ μμμΌλ©°, μ΄λ νν μ€μμ μμΈμ΄ λμ΄ RFCλ₯Ό ν΅ν΄ μ κ±°λμμ΅λλ€. νμ§λ§ μ¬μ ν μ§μλλ―λ‘, λ΄λΉκ²μ΄μ
κ°λμ μΈ λ²μ§Έ μΈμλ₯Ό μ λ¬ν μ μμ΅λλ€. μ΄ κ²½μ°, λ΄λΉκ²μ΄μ
κ°λλ₯Ό ν΅κ³Όν λ λ°λμ ν λ²λ§ next
λ₯Ό νΈμΆν΄μΌ ν©λλ€. μ¬λ¬ λ² λ±μ₯ν μ μμ§λ§, λ
Όλ¦¬ κ²½λ‘κ° κ²ΉμΉμ§ μλ κ²½μ°μλ§ κ·Έλ κ³ , κ·Έλ μ§ μμΌλ©΄ ν
μ΄ ν΄κ²°λμ§ μκ±°λ μ€λ₯κ° λ°μν©λλ€. λ€μμ μΈμ¦λμ§ μμ μ¬μ©μλ₯Ό /login
μΌλ‘ 리λλ μ
νλ μλͺ»λ μμμ
λλ€:
// μλͺ»λ μμ
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
// μ¬μ©μκ° μΈμ¦λμ§ μμ κ²½μ°, `next`κ° λ λ² νΈμΆλ¨
next()
})
μ¬λ°λ₯Έ λ²μ μ λ€μκ³Ό κ°μ΅λλ€:
// μ¬λ°λ₯Έ μμ
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})
μ μ Resolve κ°λ β
router.beforeResolve
λ₯Ό μ¬μ©νμ¬ μ μ κ°λλ₯Ό λ±λ‘ν μ μμ΅λλ€. μ΄λ router.beforeEach
μ μ μ¬νκ² λͺ¨λ λ΄λΉκ²μ΄μ
μμ νΈλ¦¬κ±°λμ§λ§, resolve κ°λλ λ΄λΉκ²μ΄μ
μ΄ νμ λκΈ° μ§μ , λͺ¨λ μ»΄ν¬λνΈ λ΄ κ°λμ λΉλκΈ° λΌμ°νΈ μ»΄ν¬λνΈκ° ν΄κ²°λ νμ νΈμΆλ©λλ€. λ€μμ 컀μ€ν
meta μμ± requiresCamera
κ° μ μλ λΌμ°νΈμμ μ¬μ©μκ° μΉ΄λ©λΌ μ κ·Ό κΆνμ λΆμ¬νλμ§ νμΈνλ μμμ
λλ€:
router.beforeResolve(async to => {
if (to.meta.requiresCamera) {
try {
await askForCameraPermission()
} catch (error) {
if (error instanceof NotAllowedError) {
// ... μ€λ₯λ₯Ό μ²λ¦¬ν ν λ΄λΉκ²μ΄μ
μ·¨μ
return false
} else {
// μκΈ°μΉ μμ μ€λ₯, λ΄λΉκ²μ΄μ
μ·¨μ λ° μ€λ₯λ₯Ό μ μ νΈλ€λ¬λ‘ μ λ¬
throw error
}
}
}
})
router.beforeResolve
λ μ¬μ©μκ° νμ΄μ§μ μ§μ
ν μ μλ κ²½μ° λ°μ΄ν°λ₯Ό κ°μ Έμ€κ±°λ κΈ°ν μμ
μ νΌνκ³ μΆμ λ μ΄μμ μΈ μμΉμ
λλ€.
μ μ After ν β
μ μ after ν
λ λ±λ‘ν μ μμ§λ§, κ°λμ λ¬λ¦¬ μ΄ ν
λ€μ next
ν¨μλ₯Ό λ°μ§ μμΌλ©° λ΄λΉκ²μ΄μ
μ μν₯μ μ€ μ μμ΅λλ€:
router.afterEach((to, from) => {
sendToAnalytics(to.fullPath)
})
μ΄ ν λ€μ λΆμ, νμ΄μ§ μ λͺ© λ³κ²½, νμ΄μ§ μλ¦Όκ³Ό κ°μ μ κ·Όμ± κΈ°λ₯ λ± λ€μν μ©λλ‘ μ μ©ν©λλ€.
λν λ΄λΉκ²μ΄μ μ€ν¨λ₯Ό μΈ λ²μ§Έ μΈμλ‘ λ°μν©λλ€:
router.afterEach((to, from, failure) => {
if (!failure) sendToAnalytics(to.fullPath)
})
λ΄λΉκ²μ΄μ μ€ν¨μ λν μμΈν λ΄μ©μ κ°μ΄λλ₯Ό μ°Έκ³ νμΈμ.
κ°λ λ΄μμμ μ μ μ£Όμ β
Vue 3.3λΆν°λ λ΄λΉκ²μ΄μ
κ°λ λ΄μμ inject()
λ₯Ό μ¬μ©ν μ μμ΅λλ€. μ΄λ pinia μ€ν μ΄μ κ°μ μ μ μμ±μ μ£Όμ
νλ λ° μ μ©ν©λλ€. app.provide()
λ‘ μ 곡λ λͺ¨λ κ²μ router.beforeEach()
, router.beforeResolve()
, router.afterEach()
λ΄μμλ μ κ·Όν μ μμ΅λλ€:
// main.ts
const app = createApp(App)
app.provide('global', 'hello injections')
// router.ts λλ main.ts
router.beforeEach((to, from) => {
const global = inject('global') // 'hello injections'
// pinia μ€ν μ΄
const userStore = useAuthStore()
// ...
})
λΌμ°νΈλ³ κ°λ β
λΌμ°νΈμ μ€μ κ°μ²΄μ beforeEnter
κ°λλ₯Ό μ§μ μ μν μ μμ΅λλ€:
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
// λ΄λΉκ²μ΄μ
κ±°λΆ
return false
},
},
]
beforeEnter
κ°λλ ν΄λΉ λΌμ°νΈμ μ§μ
ν λλ§ νΈλ¦¬κ±°λλ©°, params
, query
λλ hash
κ° λ³κ²½λ λ(μ: /users/2
μμ /users/3
μΌλ‘ μ΄λνκ±°λ /users/2#info
μμ /users/2#projects
λ‘ μ΄λ)μλ νΈλ¦¬κ±°λμ§ μμ΅λλ€. μ€μ§ λ€λ₯Έ λΌμ°νΈμμ μ§μ
ν λλ§ νΈλ¦¬κ±°λ©λλ€.
beforeEnter
μ ν¨μ λ°°μ΄μ μ λ¬ν μλ μμ΅λλ€. μ΄λ μ¬λ¬ λΌμ°νΈμμ κ°λλ₯Ό μ¬μ¬μ©ν λ μ μ©ν©λλ€:
function removeQueryParams(to) {
if (Object.keys(to.query).length)
return { path: to.path, query: {}, hash: to.hash }
}
function removeHash(to) {
if (to.hash) return { path: to.path, query: to.query, hash: '' }
}
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: [removeQueryParams, removeHash],
},
{
path: '/about',
component: UserDetails,
beforeEnter: [removeQueryParams],
},
]
μ€μ²© λΌμ°νΈλ₯Ό μ¬μ©ν λ, λΆλͺ¨μ μμ λΌμ°νΈ λͺ¨λ beforeEnter
λ₯Ό μ¬μ©ν μ μμ΅λλ€. λΆλͺ¨ λΌμ°νΈμ λ°°μΉνλ©΄, λμΌν λΆλͺ¨λ₯Ό κ°μ§ μμ κ° μ΄λ μμλ νΈλ¦¬κ±°λμ§ μμ΅λλ€. μλ₯Ό λ€μ΄:
const routes = [
{
path: '/user',
beforeEnter() {
// ...
},
children: [
{ path: 'list', component: UserList },
{ path: 'details', component: UserDetails },
],
},
]
μ μμμ beforeEnter
λ /user/list
μ /user/details
κ° μ΄λ μμλ νΈμΆλμ§ μμ΅λλ€. λ λΌμ°νΈκ° λμΌν λΆλͺ¨λ₯Ό 곡μ νκΈ° λλ¬Έμ
λλ€. λ§μ½ beforeEnter
κ°λλ₯Ό details
λΌμ°νΈμ μ§μ λ°°μΉνλ©΄, λ λΌμ°νΈ κ° μ΄λ μ νΈμΆλ©λλ€.
TIP
λΌμ°νΈ meta νλμ μ μ λ΄λΉκ²μ΄μ κ°λλ₯Ό μ¬μ©νμ¬ λΌμ°νΈλ³ κ°λμ μ μ¬ν λμμ ꡬνν μ μμ΅λλ€.
μ»΄ν¬λνΈ λ΄ κ°λ β
λ§μ§λ§μΌλ‘, λΌμ°νΈ μ»΄ν¬λνΈ(λΌμ°ν° μ€μ μ μ λ¬λ μ»΄ν¬λνΈ) λ΄λΆμ μ§μ λΌμ°νΈ λ΄λΉκ²μ΄μ κ°λλ₯Ό μ μν μ μμ΅λλ€.
Options API μ¬μ© β
λ€μ μ΅μ μ λΌμ°νΈ μ»΄ν¬λνΈμ μΆκ°ν μ μμ΅λλ€:
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
<script>
export default {
beforeRouteEnter(to, from) {
// μ΄ μ»΄ν¬λνΈλ₯Ό λ λλ§νλ λΌμ°νΈκ° νμ λκΈ° μ μ νΈμΆλ©λλ€.
// `this` μ»΄ν¬λνΈ μΈμ€ν΄μ€μ μ κ·Όν μ μμ΅λλ€.
// μ΄ κ°λκ° νΈμΆλ λ μ»΄ν¬λνΈκ° μμ§ μμ±λμ§ μμκΈ° λλ¬Έμ
λλ€!
},
beforeRouteUpdate(to, from) {
// μ΄ μ»΄ν¬λνΈλ₯Ό λ λλ§νλ λΌμ°νΈκ° λ³κ²½λμμ§λ§, μ΄ μ»΄ν¬λνΈκ° μ λΌμ°νΈμμ μ¬μ¬μ©λ λ νΈμΆλ©λλ€.
// μλ₯Ό λ€μ΄, `/users/:id`μ κ°μ λΌμ°νΈμμ `/users/1`κ³Ό `/users/2` μ¬μ΄λ₯Ό μ΄λν λ,
// λμΌν `UserDetails` μ»΄ν¬λνΈ μΈμ€ν΄μ€κ° μ¬μ¬μ©λλ©°, μ΄ ν
μ΄ νΈμΆλ©λλ€.
// μ΄λ μ»΄ν¬λνΈκ° λ§μ΄νΈλμ΄ μμΌλ―λ‘, λ΄λΉκ²μ΄μ
κ°λλ `this` μ»΄ν¬λνΈ μΈμ€ν΄μ€μ μ κ·Όν μ μμ΅λλ€.
},
beforeRouteLeave(to, from) {
// μ΄ μ»΄ν¬λνΈλ₯Ό λ λλ§νλ λΌμ°νΈμμ λ²μ΄λκΈ° μ§μ μ νΈμΆλ©λλ€.
// `beforeRouteUpdate`μ λ§μ°¬κ°μ§λ‘, `this` μ»΄ν¬λνΈ μΈμ€ν΄μ€μ μ κ·Όν μ μμ΅λλ€.
},
}
</script>
beforeRouteEnter
κ°λλ this
μ μ κ·Όν μ μμ΅λλ€. μ΄ κ°λλ λ΄λΉκ²μ΄μ
μ΄ νμ λκΈ° μ μ νΈμΆλλ―λ‘, μ§μ
νλ μ μ»΄ν¬λνΈκ° μμ§ μμ±λμ§ μμκΈ° λλ¬Έμ
λλ€.
νμ§λ§, next
μ μ½λ°±μ μ λ¬νμ¬ μΈμ€ν΄μ€μ μ κ·Όν μ μμ΅λλ€. λ΄λΉκ²μ΄μ
μ΄ νμ λλ©΄ μ½λ°±μ΄ νΈμΆλκ³ , μ»΄ν¬λνΈ μΈμ€ν΄μ€κ° μΈμλ‘ μ λ¬λ©λλ€:
beforeRouteEnter (to, from, next) {
next(vm => {
// `vm`μ ν΅ν΄ μ»΄ν¬λνΈ κ³΅κ° μΈμ€ν΄μ€μ μ κ·Ό
})
}
beforeRouteEnter
λ§μ΄ next
μ μ½λ°±μ μ λ¬νλ κ²μ μ§μν©λλ€. beforeRouteUpdate
μ beforeRouteLeave
μμλ μ΄λ―Έ this
κ° μ¬μ© κ°λ₯νλ―λ‘, μ½λ°± μ λ¬μ΄ λΆνμνλ©° μ§μλμ§ μμ΅λλ€:
beforeRouteUpdate (to, from) {
// κ·Έλ₯ `this`λ₯Ό μ¬μ©νμΈμ
this.name = to.params.name
}
leave κ°λλ μ£Όλ‘ μ¬μ©μκ° μ μ₯νμ§ μμ νΈμ§ λ΄μ©μ κ°μ§ μ±λ‘ λΌμ°νΈλ₯Ό λ λλ κ²μ λ°©μ§νλ λ° μ¬μ©λ©λλ€. false
λ₯Ό λ°ννμ¬ λ΄λΉκ²μ΄μ
μ μ·¨μν μ μμ΅λλ€.
beforeRouteLeave (to, from) {
const answer = window.confirm('μ λ§λ‘ λ λμκ² μ΅λκΉ? μ μ₯λμ§ μμ λ³κ²½μ¬νμ΄ μμ΅λλ€!')
if (!answer) return false
}
Composition API μ¬μ© β
Composition APIλ‘ μ»΄ν¬λνΈλ₯Ό μμ±νλ κ²½μ°, onBeforeRouteUpdate
μ onBeforeRouteLeave
λ₯Ό ν΅ν΄ μ
λ°μ΄νΈ λ° leave κ°λλ₯Ό μΆκ°ν μ μμ΅λλ€. μμΈν λ΄μ©μ Composition API μΉμ
μ μ°Έκ³ νμΈμ.
μ 체 λ΄λΉκ²μ΄μ ν΄κ²° νλ¦ β
- λ΄λΉκ²μ΄μ νΈλ¦¬κ±°.
- λΉνμ±νλ μ»΄ν¬λνΈμ
beforeRouteLeave
κ°λ νΈμΆ. - μ μ
beforeEach
κ°λ νΈμΆ. - μ¬μ¬μ©λλ μ»΄ν¬λνΈμ
beforeRouteUpdate
κ°λ νΈμΆ. - λΌμ°νΈ μ€μ μ
beforeEnter
νΈμΆ. - λΉλκΈ° λΌμ°νΈ μ»΄ν¬λνΈ ν΄κ²°.
- νμ±νλ μ»΄ν¬λνΈμ
beforeRouteEnter
νΈμΆ. - μ μ
beforeResolve
κ°λ νΈμΆ. - λ΄λΉκ²μ΄μ νμ .
- μ μ
afterEach
ν νΈμΆ. - DOM μ λ°μ΄νΈ νΈλ¦¬κ±°.
- μΈμ€ν΄μ€νλ μΈμ€ν΄μ€μ ν¨κ»
beforeRouteEnter
κ°λμ μ λ¬λ μ½λ°± νΈμΆ.