Vue Router 4 is in beta and it’s subject to change.
To build a single page app easily, we got to add routing so that URLs will be mapped to components that are rendered.
In this article, we’ll look at how to use Vue Router 4 with Vue 3.
Async Scrolling Behavior
We can change the scrolling behavior to be async.
To do that, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js"></script>
<title>App</title>
</head>
<body>
<div id="app">
<p>
<router-link to="/foo">foo</router-link>
<router-link to="/bar">bar</router-link>
</p>
<router-view></router-view>
</div>
<script>
const Foo = {
template: `<div>
<p v-for='n in 100'>{{n}}</p>
</div>`
};
const Bar = {
template: `<div>
<p v-for='n in 100'>{{n}}</p>
</div>`
};
const routes = [
{
path: "/foo",
component: Foo
},
{
path: "/bar",
component: Bar
}
];
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ left: 0, top: 500 });
}, 500);
});
}
});
const app = Vue.createApp({});
app.use(router);
app.mount("#app");
</script>
</body>
</html>
We have the scrollBehavior
method that returns a promise that resolves to an object with the scroll position.
The left
and top
properties are the new properties for the x and y coordinates.
They replace the x
and y
properties in Vue Router 3.
Lazy Loading Routes
We can lazy load routes in our app.
For example, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="[https://unpkg.com/vue@next](https://unpkg.com/vue@next)"></script>
<script src="[https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js](https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js)"></script>
<title>App</title>
</head>
<body>
<div id="app">
<p>
<router-link to="/foo">foo</router-link>
<router-link to="/bar">bar</router-link>
</p>
<router-view></router-view>
</div>
<script>
const Foo = () =>
Promise.resolve({
template: `<div>foo</div>`
});
const Bar = () =>
Promise.resolve({
template: `<div>bar</div>`
});
const routes = [
{
path: "/foo",
component: Foo
},
{
path: "/bar",
component: Bar
}
];
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes
});
const app = Vue.createApp({});
app.use(router);
app.mount("#app");
</script>
</body>
</html>
We have the Foo
and Bar
components.
They are defined by creating a promise that resolves to the component definition.
With Webpack, we can also use the import
function to import our component.
For example, we can write:
import('./Foo.vue')
import
returns a promise that resolves to the component, and it works the same way as the promise definition above.
Grouping Components in the Same Chunk
We can group components in the same chunk bu creating components with functions:
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
We have comments with webpackChunkName
with the chunk name.
Navigation Failures
We can handle navigation errors with programmatic navigation.
For example, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://unpkg.com/vue@next"></script>
<script src="https://unpkg.com/vue-router@4.0.0-beta.7/dist/vue-router.global.js"></script>
<title>App</title>
</head>
<body>
<div id="app">
<p>
<router-link to="/foo">foo</router-link>
<a href="#" [@click](http://twitter.com/click "Twitter profile for @click").stop="go">bar</a>
</p>
<router-view></router-view>
</div>
<script>
const Foo = {
template: `<div>foo</div>`
};
const Bar = {
template: `<div>bar</div>`,
beforeRouteEnter(to, from, next) {
next(new Error());
}
};
const routes = [
{
path: "/foo",
component: Foo
},
{
path: "/bar",
component: Bar
}
];
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes
});
const app = Vue.createApp({
methods: {
go() {
this.$router.push("/bar").catch((failure) => {
console.log(failure);
});
}
}
});
app.use(router);
app.mount("#app");
</script>
</body>
</html>
to handle navigation errors.
We a beforeRouterEnter
method in the Bar
component.
It calls next
with an Error
instance within the method.
This will cause the Error
instance to be shown in the console.
In the root Vue instance, we have the go
method that tries to go to the /bar
route with the push
method.
The catch
method’s callback has the failure
parameter that has the Error
instance that’s thrown.
Conclusion
We can change scrolling behavior to be async.
Also, components can be grouped into chunks and lazy-loaded.
Finally, we can handle errors that are raised from programmatic navigation.