In the last post, More Advanced Routing with Vue, we covered using Transitions with Vue Router. This time we’ll cover Data Fetching with Vue Router.
Data Fetching allows us to load asynchronous data in our routed components. We can also specify whether data is fetched before or after a component is loaded. Both of these strategies are equally viable but have different implementations. We’ll cover both.
Since this is yet another post about advanced Vue Router techniques, we’ll assume you’re already familiar with the basic setup. However, let’s define a starting point that we’ll use for the rest of the post:
# Yarn
$ yarn add vue-router
# npm
$ npm install vue-router --save
import Vue from 'vue';
import VueRouter from 'vue-router';
import App from './App';
import Swamp from './components/Swamp';
import Gator from './components/Gator';
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{ path: '/swamp', component: Swamp },
{ path: '/gator', component: Gator }
]
});
new Vue({
render: h => h(App),
router
}).$mount('#app')
<template>
<div id="app">
<div class="nav">
<router-link to="/swamp">Swamp</router-link> |
<router-link to="/gator">Gator</router-link>
</div>
<hr />
<div class="router-view">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default { name: 'App' }
</script>
<template>
<div>Welcome to the Swamp, {{ name }}!</div>
</template>
<script>
export default {
name: 'Swamp',
data() {
return { name: null }
},
}
</script>
<template>
<div>Howdy, Gator {{ name }}!</div>
</template>
<script>
export default {
name: 'Gator',
data() {
return { name: null }
}
}
</script>
Let’s say we had a function that mocked a simple HTTP GET
called pretendGet()
:
export default (callback) => {
setTimeout(() => {
callback(null, 'Alice');
}, 500);
}
After 500ms pretendGet()
will return the string 'Alice'
to the callback method callback
. We’ll use this to mock a server request in the following examples.
Fetching before navigation allows us to ensure that our routed components have the data they need before being displayed to the user. In this approach we added a beforeRouteEnter
method which Vue Router calls when the user requests to navigate to this component but before it has loaded. We also define a beforeRouteUpdate
method which is called when the route changes. This is useful if you’re fetching data related to a route parameter which is accessible via to.params
.
import pretendGet from '../scripts/pretendGet';
export default {
name: 'Gator',
data() {
return { name: null }
},
// Component not loaded yet
beforeRouteEnter(to, from, next) {
pretendGet((err, name) => {
next(vm => vm.setName(err, name));
});
},
// Component already loaded and route changes
beforeRouteUpdate(to, from, next) {
this.name = null;
pretendGet((err, name) => {
this.setName(err, name);
next();
});
},
methods: {
setName(err, name) {
if (err) {
console.error(err);
} else {
this.name = name;
}
}
}
}
Keep in mind that navigation will not happen until data is fetched. Because of this, it’s a good idea to display some kind of progress bar or indicator that data is being fetched. If there’s an error, it would also be a good idea to display that as well.
Fetching after navigation is also a valid approach. In this case we’ll utilize the created()
lifecycle hook to call our data fetching method fetchName()
. We’ll also define a watch
property on $route
so we can call fetchName()
whenever the route changes.
import pretendGet from '../scripts/pretendGet';
export default {
name: 'Swamp',
data() {
return { name: null }
},
created() {
this.fetchName();
},
watch: {
// Re-fetch when route changes
'$route': 'fetchName'
},
methods: {
fetchName() {
pretendGet((err, name) => {
if (err) {
console.error(err);
} else {
this.name = name;
}
});
}
}
}
Keep in mind that with this approach we’ll have to account for data not being ready when the component is first rendered. It’s a good idea to include placeholders or skeleton placeholders along with indicators to let the user know that data is being fetched along with any errors that might occur.
Vue Router Data Fetching is a great way to ensure a smooth user experience for your components that rely on fetching data from external sources. Fetching before navigation is a good approach if you’re a fan of using app-wide notifications or progress indicators. If you’d rather handle this kind of stuff on a component level then fetching after navigation might be the right approach for you. As always, make sure to read the docs!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!