在激活阶段被调用,在 activate
被断定( resolved ,指该函数返回的 promise 被 resolve )。用于加载和设置当前组件的数据。
调用 transition.next(data)
会为组件的 data
相应属性赋值。例如,使用 { a: 1, b: 2 }
,路由会调用 component.$set('a', 1)
以及 component.$set('b', 2)
。
可选择性返回一个promise
resolve(data)
-> transition.next(data)
reject(reason)
-> transition.abort(reason)
data
切换钩子会在 activate
被断定( resolved )以及界面切换之前被调用。切换进来的组件会得到一个名为 $loadingroutedata
的元属性,其初始值为 false
,在 data
钩子函数被断定后会被赋值为 true
。这个属性可用来会切换进来的组件展示加载效果。
data
钩子和 activate
钩子的不同之处在于:
data
在每次路由变动时都会被调用,即使是当前组件可以被重用的时候,但是 activate
尽在组件是新创建时才会被调用。
假设我们有一个组件对应于路由 /message/:id
,当前用户所处的路径是 /message/1
。当用户浏览 /message/2
时,当前组件可以被重用,所以 activate
不会被调用。但是我们需要根据新的 id
参数去获取和更新数据,所以大部分情况下,在 data
中获取数据比在 activate
中更加合理。
activate
的作用是控制切换到新组件的时机。data
切换钩子会在 activate
被断定( resolved )以及界面切换之前被调用,所以数据获取和新组件的切入动画是并行进行的,而且在 data
被断定( resolved )之前,组件会处在“加载”状态。
从用户体验的角度来看一下两者的区别:
如果我们等到获取到数据之后再显示新组件,用户会感觉在切换前界面被卡住了。
这么说的话,如果你想等到数据获取之后再切换视图,可以在组件定义路由选项时,添加 waitfordata: true
参数。
调用 transition.next
:
route: {
data: function (transition) {
settimeout(function () {
transition.next({
message: 'data fetched!'
})
}, 1000)
}
}
返回 promise :
route: {
data: function () {
return messageservice
.fetch(transition.to.params.messageid)
.then(function (message) {
return { message: message }
})
}
}
并发请求,利用 promise & es6 :
route: {
data ({ to: { params: { userid }}}) {
return promise.all([
userservice.get(userid),
postsservice.getforuser(userid)
]).then(([user, post]) => ({ user, post }))
}
}
与上面等价的 es5 版本:
route: {
data (transition) {
var userid = transition.to.params.userid
return promise.all([
userservice.get(userid),
postsservice.getforuser(userid)
]).then(function (data) {
return {
user: data[0],
posts: data[1]
}
})
}
}
在模板中使用 $loadingroutedata
:
<div class="view">
<div v-if="$loadingroutedata">loading ...</div>
<div v-if="!$loadingroutedata">
<user-profile user="{{user}}"></user-profile>
<user-post v-repeat="post in posts"></user-post>
</div>
</div>
上面的并发请求示例需要我们自己调用 promise.all
来将多个 promise 合并成一个,并且最终处理返回的数据时也有些繁琐。vue-router
在这里提供了一个语法糖,让我们可以在 data
函数中直接返回一个包含 promise 的对象(当然也可以包含非 promise 的值)。利用这个语法糖和 es6,我们可以这样实现上面的例子:
route: {
data: ({ to: { params: { userid }}}) => ({
user: userservice.get(userid),
post: postsservice.getforuser(userid)
})
}
路由器将会在这两个 promise resolve 之后的值分别赋值给组件的 user
和 post
属性。同时,$loadingroutedata
会在所有的 promise 都 resolve 之后被设置为 false
。
上面的例子在 es5 下可以这样写:
route: {
data: function (transition) {
var userid = transition.to.params.userid
return {
user: userservice.get(userid),
post: postsservice.getforuser(userid)
}
}
}