You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sometimes you need to fetch data from the server before rendering a route. For
4
-
example, before visiting a user profile, you have to fetch his data from the
5
-
server. We can achieve this in two different ways. Each way provide a different
6
-
UX approach and both of them are valid designs.
3
+
Sometimes you need to fetch data from the server when a route is activated. For example, before rendering a user profile, you need to fetch the user's data from the server. We can achieve this in two different ways:
7
4
5
+
-**Fetching After Navigation**: perform the navigation first, and fetch data in the incoming component's lifecycle hook. Display a loading state while data is being fetched.
8
6
9
-
## Fetching before navigation
7
+
-**Fetching Before Navigation**: Fetch data before navigation in the route enter guard, and perform the navigation after data has been fetched.
10
8
11
-
This method consists on fetching the data before actually navigating to the new
12
-
route. For those using vue-router 1, this works as the `activate` hook. In
13
-
vue-router 2 you use the `beforeRouteEnter` hook to control the navigation flow.
14
-
You get access to the `route`, a `redirect` function and a `next` callback to
15
-
let the navigation end. Not calling the `next` callback will simply cancel the
16
-
navigation. Note that this hook is
9
+
Technically, both are valid choices - it ultimately depends on the user experience you are aiming for.
10
+
11
+
## Fetching After Navigation
12
+
13
+
When using this approach, we navigate and render the incoming component immediately, and fetch data in the component's `created` hook. It gives us the opportunity to display a loading state while the data is being fetched over the network, and we can also handle loading differently for each view.
14
+
15
+
Let's assume we have a `Post` component that needs to fetch the data for a post based on `$route.params.id`:
16
+
17
+
```html
18
+
<template>
19
+
<divclass="post">
20
+
<divclass="loading"v-if="loading">
21
+
Loading...
22
+
</div>
23
+
24
+
<divv-if="error"class="error">
25
+
{{ error }}
26
+
</div>
27
+
28
+
<divv-if="post"class="content">
29
+
<h2>{{ post.title }}</h2>
30
+
<p>{{ post.body }}</p>
31
+
</div>
32
+
</div>
33
+
</template>
34
+
```
17
35
18
36
```js
19
37
exportdefault {
@@ -24,75 +42,63 @@ export default {
24
42
error:null
25
43
}
26
44
},
27
-
beforeRouteEnter (route, redirect, next) {
45
+
created () {
28
46
// fetch the data when the view is created and the data is
29
47
// already being observed
30
-
this.fetchData(route.params.id, next)
48
+
this.fetchData()
31
49
},
32
50
watch: {
33
51
// call again the method if the route changes
34
-
$route () {
35
-
this.fetchData(this.$route.params.id)
36
-
}
52
+
'$route':'fetchData'
37
53
},
38
54
methods: {
39
-
fetchData (id, cb) {
55
+
fetchData () {
40
56
this.error=this.post=null
41
57
this.loading=true
42
-
getPost(id, (err, post) => {
58
+
// replace getPost with your data fetching util / API wrapper
59
+
getPost(this.$route.params.id, (err, post) => {
43
60
this.loading=false
44
61
if (err) {
45
62
this.error=err.toString()
46
63
} else {
47
64
this.post= post
48
65
}
49
-
cb &&cb()
50
66
})
51
67
}
52
68
}
53
69
}
54
70
```
55
71
56
-
The user still can use the application while the resource is being fetched. It
57
-
is therefore recommended to show him with a progress bar or any other indicator
58
-
that the web site is waiting for data. If, during this time, the user navigates
59
-
somewhere else by clicking on a link, the navigation waiting for data will never
60
-
take place.
61
-
62
-
## Fetching inside the view
72
+
## Fetching Before Navigation
63
73
64
-
This method consists on fetching data during the component lifecycle. It allows
65
-
you to define how the content of your view is presented while the resources are
66
-
loading. Using this approach let you handle how loading in handled differently
67
-
for each view.
68
-
69
-
Replacing `beforeRouteEnter` with `created` is almost all you need to do to
70
-
switch to the other fetching method.
74
+
With this approach we fetch the data before actually navigating to the new
75
+
route. We can perform the data fetching in the `beforeRouteEnter` guard in the incoming component, and only call `next` when the fetch is complete:
71
76
72
77
```js
73
78
exportdefault {
74
79
data () {
75
80
return {
76
-
loading:false,
77
81
post:null,
78
82
error:null
79
83
}
80
84
},
81
-
created () {
82
-
// fetch the data when the view is created and the data is
83
-
// already being observed
84
-
this.fetchData()
85
+
beforeRouteEnter (route, redirect, next) {
86
+
getPost(route.params.id, (err, post) => {
87
+
if (err) {
88
+
// display some global error message
89
+
} else {
90
+
next(vm=> {
91
+
vm.post= post
92
+
})
93
+
}
94
+
})
85
95
},
96
+
// when route changes when this component is already rendered,
97
+
// the logic will be slightly different.
86
98
watch: {
87
-
// call again the method if the route changes
88
-
'$route':'fetchData'
89
-
},
90
-
methods: {
91
-
fetchData () {
92
-
this.error=this.post=null
93
-
this.loading=true
99
+
$route () {
100
+
this.post=null
94
101
getPost(this.$route.params.id, (err, post) => {
95
-
this.loading=false
96
102
if (err) {
97
103
this.error=err.toString()
98
104
} else {
@@ -104,25 +110,4 @@ export default {
104
110
}
105
111
```
106
112
107
-
The component lifecycle will go on and once the data is fetched, the view will update acordingly. This way you can choose what to show while the data is being fetched. Here we're just displaying _Loading..._:
giving the post container a unique key triggers transitions
119
-
when the post id changes.
120
-
-->
121
-
<divv-if="post"class="content":key="post.id">
122
-
<h2>{{ post.title }}</h2>
123
-
<p>{{ post.body }}</p>
124
-
</div>
125
-
</transition>
126
-
</div>
127
-
</template>
128
-
```
113
+
The user will stay on the current view while the resource is being fetched for the incoming view. It is therefore recommended to display a progress bar or some kind of indicator while the data is being fetched. If the data fetch fails, it's also necessary to display some kind of global warning message.
0 commit comments