Data structure

data(transition) [-> Promise]

Arguments

Return Value

Details

The data transition hook is called immediately after the activate hook is resolved, and right before the view switching is executed. The entering component gets a $loadingRouteData meta property, which starts with value false and set to true when the data hook is resolved. This property can be used to display a loading state for the entering component.

The data hook is different from activate in that:

  1. data is also called every time the route changes, even if the current component is reused, while activate is only called when component is newly created.

Imagine we have a component for the route /message/:id, and we are currently on /message/1. When the user navigates to /message/2, the current component can be reused, so the activate hook will not get called. But we do want to fetch and update the data based on the new id param, so in most cases it makes sense to do data fetching in data instead of activate.

  1. activate‘s respondibility is controlling the timing of switching to the new component. In comparison, data is called right after activate is resolved and right before the view switching happens, so the data fetching and the new component’s entering animation will go in parallel, and the component will be in a “loading” state before data is resolved.

Let’s consider the difference in the User Experience here:

Examples

By calling transition.next:

1
2
3
4
5
6
7
8
9
10
route: {
  data: function (re) {
    var msg = 'data fetched!'
    setTimeout(function () {
      re.next({
        message: msg
      })
    }, 1000)
  }
}

By returning a Promise:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var fun = messageService
var api = fun.isLoggedIn

var obj = transition.to
var params = obj?.params
var id = params.messageId
route: {
  data: function () {
    return  api.fetch(id)
      .then(function(msg) {
        return { 
          message: msg
        }
      })
  }
}

Parallel requests, with Promise & ES6:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var reqs = [
  userService.
  get(userId),
  postsService.
  getForUser(userId)
]
route: {
  data ({ to: {
    params: {
      userId
    }
  }}) {
    return Promise.all(reqs)
    .then(([user,post]) => {
      return {user, post}
    })
  }
}

Equivalent of above in ES5:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var obj = transition.to
var params = obj?.params
var id = params.messageId
route: {
  data (tr) {
    return Promise.all([
      userService
      .get(id),
      postsService
      .getForUser(id)
    ]).then(function(data) {
      return {
        user: data[0],
        posts: data[1]
      }
    })
  }
}

Using $loadingRouteData in templates:

1
2
3
4
5
6
7
8
9
10
11
<div v-if="$loadingRouteData">
  Loading ...
</div>
<div v-if="!$loadingRouteData">
  <user-profile user="">
  </user-profile>
  <user-post 
    v-repeat="row in posts"
  >
  </user-post>
</div>