vue ssr疑问点
Jmingzi opened this issue · comments
1. 关于getMatchedComponents
在entry-server
中,根据当前路由匹配出的组件,只包含路由组件么?而不包含路由组件中引用的子组件。
例如:
// route Component A
// 引入了 BottomTab 组件,在BottomTab组件中需要预取数据
<route-a>
<bottom-tab />
</route-a>
而此时组件BottomTab,并没有被getMatchedComponents匹配到。
2.关于在客户端预取数据
起初看到官方文档数据的预取与渲染
这里时,对客户端数据的预取很不理解,客户端为何要预取数据?
官方有2种实现:
// 1. 在entry-client.js中实现
router.onReady(() => {
// 在路由初始化完成后,注册钩子函数去处理路由变化时,对组件的一些操作,比如数据预取。
router.beforeResolve((to, from, next) => {
// 在这里会根据to, from,来getMatchedComponents
// 从而匹配出相应的路由组件
// 筛选出to和from不一致的情况下,也就是跳转的路由与当前不一致时,才去预取数据
// 为什么会这么做?我猜是在这种情况下,例如获取文章详情,或分类列表
// 它们的路由看起来是这样的:`/detail/1`,`/list/1`,当路由变化时,组件并没有改变
// 所以不需要去预取数据的,所以也就避免了二次预取(double-fetch)已有的数据
const matched = router.getMatchedComponents(to)
const prevMatched = router.getMatchedComponents(from)
let diffed = false
const activated = matched.filter((c, i) => {
return diffed || (diffed = (prevMatched[i] !== c))
})
if (!activated.length) {
return next()
}
})
})
我们再来看第二种实现来论证这个观点:
// 2. 通过全局的mixin,来注册生命周期钩子函数
Vue.mixin({
// beforeMount只会在组件初始化时调用
// 在`/detail/1`,`/list/1`这种路由发生变化时,是不会调用的
// 也就论证了上面的说法成立
beforeMount () {
const { asyncData } = this.$options
if (asyncData) {
// 将获取数据操作分配给 promise
// 以便在组件中,我们可以在数据准备就绪后
// 通过运行 `this.dataPromise.then(...)` 来执行其他任务
this.dataPromise = asyncData({
store: this.$store,
route: this.$route
})
}
}
})
在实际的项目中,规避double-fetch
的做法有很多,客户端数据预取的实现也有很多,通常我们是在created
钩子中去做这个事情,例如:
{
created() {
if (this.list === null) {
// 当list为null时,才去取数据
this.fetchData()
}
}
}
我想,这跟官方的数据的预取
是一个道理吧