0
# Composition API
1
2
Vue 3-style composables for accessing router functionality in composition API components. These functions provide reactive access to router state and navigation controls for use with Vue 2.7+ composition API or @vue/composition-api plugin.
3
4
```javascript
5
import { useRouter, useRoute, onBeforeRouteUpdate, onBeforeRouteLeave, useLink } from 'vue-router/composables';
6
```
7
8
## Capabilities
9
10
### Core Composables
11
12
Access router instance and current route reactively.
13
14
```javascript { .api }
15
/**
16
* Access the router instance
17
* @returns VueRouter instance
18
*/
19
function useRouter(): VueRouter;
20
21
/**
22
* Access the current route (reactive)
23
* @returns Reactive route object that updates when route changes
24
*/
25
function useRoute(): Route;
26
```
27
28
**Usage Examples:**
29
30
```javascript
31
import { useRouter, useRoute } from 'vue-router/composables';
32
import { computed, watch } from 'vue';
33
34
export default {
35
setup() {
36
const router = useRouter();
37
const route = useRoute();
38
39
// Reactive route properties
40
const userId = computed(() => route.params.id);
41
const currentPath = computed(() => route.path);
42
const queryParams = computed(() => route.query);
43
44
// Watch route changes
45
watch(() => route.params.id, (newId, oldId) => {
46
console.log(`User changed from ${oldId} to ${newId}`);
47
loadUserData(newId);
48
});
49
50
// Navigation methods
51
const navigateToUser = (id) => {
52
router.push({ name: 'user', params: { id }});
53
};
54
55
const goBack = () => {
56
router.go(-1);
57
};
58
59
return {
60
userId,
61
currentPath,
62
queryParams,
63
navigateToUser,
64
goBack
65
};
66
}
67
};
68
```
69
70
### Navigation Guards Composables
71
72
Register navigation guards that are automatically cleaned up when component is unmounted.
73
74
```javascript { .api }
75
/**
76
* Register guard for route updates (when component is reused)
77
* @param guard - Navigation guard function
78
*/
79
function onBeforeRouteUpdate(guard: NavigationGuard): void;
80
81
/**
82
* Register guard for leaving current route
83
* @param guard - Navigation guard function
84
*/
85
function onBeforeRouteLeave(guard: NavigationGuard): void;
86
```
87
88
**Usage Examples:**
89
90
```javascript
91
import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router/composables';
92
import { ref, onMounted } from 'vue';
93
94
export default {
95
setup() {
96
const userData = ref(null);
97
const hasUnsavedChanges = ref(false);
98
const loading = ref(false);
99
100
// Handle route parameter changes
101
onBeforeRouteUpdate(async (to, from, next) => {
102
if (to.params.id !== from.params.id) {
103
loading.value = true;
104
try {
105
userData.value = await fetchUser(to.params.id);
106
next();
107
} catch (error) {
108
console.error('Failed to load user:', error);
109
next(false); // Cancel navigation
110
} finally {
111
loading.value = false;
112
}
113
} else {
114
next();
115
}
116
});
117
118
// Prevent leaving with unsaved changes
119
onBeforeRouteLeave((to, from, next) => {
120
if (hasUnsavedChanges.value) {
121
const confirmed = window.confirm(
122
'You have unsaved changes. Are you sure you want to leave?'
123
);
124
next(confirmed);
125
} else {
126
next();
127
}
128
});
129
130
const saveChanges = async () => {
131
// Save logic
132
hasUnsavedChanges.value = false;
133
};
134
135
return {
136
userData,
137
hasUnsavedChanges,
138
loading,
139
saveChanges
140
};
141
}
142
};
143
```
144
145
### Link Composable
146
147
Access RouterLink functionality programmatically with reactive state.
148
149
```javascript { .api }
150
/**
151
* RouterLink composable options
152
*/
153
interface RouterLinkOptions {
154
/** Route location to link to */
155
to: Route | Ref<Route>;
156
/** Use replace instead of push */
157
replace?: boolean;
158
}
159
160
/**
161
* RouterLink functionality as composable
162
* @param options - Link configuration
163
* @returns Reactive link state and navigation function
164
*/
165
function useLink(options: RouterLinkOptions): {
166
/** Computed route object */
167
route: ComputedRef<Route>;
168
/** Whether link is active */
169
isActive: ComputedRef<boolean>;
170
/** Whether link is exact active */
171
isExactActive: ComputedRef<boolean>;
172
/** Resolved href */
173
href: ComputedRef<string>;
174
/** Navigation function */
175
navigate: () => Promise<void>;
176
};
177
```
178
179
**Usage Examples:**
180
181
```javascript
182
import { useLink } from 'vue-router/composables';
183
import { ref, computed } from 'vue';
184
185
export default {
186
setup() {
187
const selectedUser = ref('123');
188
189
// Dynamic link based on reactive data
190
const userLink = useLink({
191
to: computed(() => ({
192
name: 'user',
193
params: { id: selectedUser.value }
194
}))
195
});
196
197
// Custom navigation with confirmation
198
const handleNavigation = async () => {
199
const confirmed = await showConfirmDialog('Navigate to user?');
200
if (confirmed) {
201
userLink.navigate();
202
}
203
};
204
205
// Multiple links
206
const links = computed(() => [
207
useLink({ to: { name: 'home' }}),
208
useLink({ to: { name: 'about' }}),
209
useLink({ to: { name: 'contact' }})
210
]);
211
212
return {
213
selectedUser,
214
userLink,
215
handleNavigation,
216
links
217
};
218
}
219
};
220
```
221
222
### Route Information Composables
223
224
Extract specific route information reactively.
225
226
```javascript { .api }
227
/**
228
* Utility composables for common route data access patterns
229
*/
230
function useRouteParams(): ComputedRef<Dictionary<string>>;
231
function useRouteQuery(): ComputedRef<Dictionary<string | (string | null)[]>>;
232
function useRoutePath(): ComputedRef<string>;
233
function useRouteName(): ComputedRef<string | null | undefined>;
234
```
235
236
**Usage Examples:**
237
238
```javascript
239
// Custom utility composables (can be created)
240
import { useRoute } from 'vue-router/composables';
241
import { computed } from 'vue';
242
243
// Create reusable route utilities
244
function useRouteParams() {
245
const route = useRoute();
246
return computed(() => route.params);
247
}
248
249
function useRouteQuery() {
250
const route = useRoute();
251
return computed(() => route.query);
252
}
253
254
function useRoutePath() {
255
const route = useRoute();
256
return computed(() => route.path);
257
}
258
259
export default {
260
setup() {
261
const params = useRouteParams();
262
const query = useRouteQuery();
263
const path = useRoutePath();
264
265
// Type-safe parameter access
266
const userId = computed(() => params.value.id);
267
const tab = computed(() => query.value.tab || 'profile');
268
269
// Derived state
270
const breadcrumbs = computed(() =>
271
path.value.split('/').filter(Boolean).map((segment, i, arr) => ({
272
name: segment,
273
path: '/' + arr.slice(0, i + 1).join('/')
274
}))
275
);
276
277
return {
278
userId,
279
tab,
280
breadcrumbs
281
};
282
}
283
};
284
```
285
286
### Navigation Composables
287
288
Create reusable navigation functions.
289
290
```javascript { .api }
291
/**
292
* Navigation utility composables
293
*/
294
function useNavigation(): {
295
push: (to: RawLocation) => Promise<Route>;
296
replace: (to: RawLocation) => Promise<Route>;
297
go: (n: number) => void;
298
back: () => void;
299
forward: () => void;
300
};
301
```
302
303
**Usage Examples:**
304
305
```javascript
306
import { useRouter } from 'vue-router/composables';
307
308
// Create navigation utilities
309
function useNavigation() {
310
const router = useRouter();
311
312
return {
313
push: (to) => router.push(to),
314
replace: (to) => router.replace(to),
315
go: (n) => router.go(n),
316
back: () => router.back(),
317
forward: () => router.forward()
318
};
319
}
320
321
// Specialized navigation composables
322
function useUserNavigation() {
323
const { push } = useNavigation();
324
325
const goToUser = (id) => push({ name: 'user', params: { id }});
326
const goToUserEdit = (id) => push({ name: 'user-edit', params: { id }});
327
const goToUserPosts = (id) => push({ name: 'user-posts', params: { id }});
328
329
return {
330
goToUser,
331
goToUserEdit,
332
goToUserPosts
333
};
334
}
335
336
export default {
337
setup() {
338
const { back, forward } = useNavigation();
339
const { goToUser } = useUserNavigation();
340
341
const handleUserClick = (user) => {
342
goToUser(user.id);
343
};
344
345
return {
346
back,
347
forward,
348
handleUserClick
349
};
350
}
351
};
352
```
353
354
### Setup and Installation
355
356
Using composables with Vue 2.7+ or composition API plugin.
357
358
```javascript { .api }
359
/**
360
* Installation requirements for composables
361
*/
362
interface ComposableSetup {
363
/** Vue 2.7+ has built-in composition API */
364
vue27Plus: boolean;
365
/** Or use @vue/composition-api plugin */
366
compositionApiPlugin: boolean;
367
}
368
```
369
370
**Usage Examples:**
371
372
```javascript
373
// With Vue 2.7+
374
import { createApp } from 'vue';
375
import VueRouter from 'vue-router';
376
377
const app = createApp({});
378
app.use(VueRouter);
379
380
// With @vue/composition-api plugin (Vue < 2.7)
381
import Vue from 'vue';
382
import VueCompositionApi from '@vue/composition-api';
383
import VueRouter from 'vue-router';
384
385
Vue.use(VueCompositionApi);
386
Vue.use(VueRouter);
387
388
// Component using composables
389
import { useRouter, useRoute } from 'vue-router/composables';
390
391
export default {
392
setup() {
393
// Must be called inside setup() function
394
const router = useRouter();
395
const route = useRoute();
396
397
// Error: Cannot be called outside setup()
398
// const router = useRouter(); // This would throw error
399
400
return {
401
// Expose to template if needed
402
};
403
}
404
};
405
```
406
407
### Error Handling with Composables
408
409
Handle navigation errors in composition API context.
410
411
```javascript { .api }
412
/**
413
* Error handling patterns for composables
414
*/
415
interface ComposableErrorHandling {
416
navigationErrors: Promise<NavigationFailure | undefined>;
417
guardErrors: Error | NavigationFailure;
418
}
419
```
420
421
**Usage Examples:**
422
423
```javascript
424
import { useRouter } from 'vue-router/composables';
425
import { isNavigationFailure, NavigationFailureType } from 'vue-router';
426
import { ref } from 'vue';
427
428
export default {
429
setup() {
430
const router = useRouter();
431
const navigationError = ref(null);
432
433
const navigateWithErrorHandling = async (to) => {
434
try {
435
await router.push(to);
436
navigationError.value = null;
437
} catch (error) {
438
if (isNavigationFailure(error, NavigationFailureType.aborted)) {
439
console.log('Navigation was aborted');
440
} else if (isNavigationFailure(error, NavigationFailureType.duplicated)) {
441
console.log('Already at destination');
442
} else {
443
navigationError.value = error;
444
console.error('Navigation failed:', error);
445
}
446
}
447
};
448
449
// Guard error handling
450
onBeforeRouteLeave((to, from, next) => {
451
try {
452
// Some validation that might throw
453
validateBeforeLeave();
454
next();
455
} catch (error) {
456
console.error('Leave guard error:', error);
457
next(false);
458
}
459
});
460
461
return {
462
navigateWithErrorHandling,
463
navigationError
464
};
465
}
466
};
467
```
468
469
## Types
470
471
```javascript { .api }
472
interface ComputedRef<T> {
473
readonly value: T;
474
}
475
476
interface Ref<T> {
477
value: T;
478
}
479
480
type Dictionary<T> = { [key: string]: T };
481
482
interface NavigationGuard {
483
(to: Route, from: Route, next: NavigationGuardNext): any;
484
}
485
486
type NavigationGuardNext = (to?: RawLocation | false | ((vm: Vue) => any) | void) => void;
487
```