没有结局的故事太多,你要习惯相遇和离别~
哈喽,宝宝们,已经到八月了呢,9012将近过去三分之二,赶紧看看今年的计划是否正常进行~
speak is cheap !
上篇文章中我们已经学习了如何把vue实例渲染成HTML字符串,还有一个重要的问题:我们的程序中,大部分都是需要获取数据,所以获取数据是灰常重要的。接下来我们看一下要怎么获取数据~
数据预取存储容器
在服务端渲染之前我们就要获取到数据,否则服务端渲染的意义就不存在了。所以在之前需要先预取和解析好这些数据。
另外,在挂载到应用程序之前,需要获取与服务端相同的数据,否则会导致混合失败。
所以,获取的数据需要在视图组件之外,即放置在专门的数据预取存储容器中。
首先,在服务端渲染之前预取数据,并将数据填充到store。此外在HTML中序列化和内联预置状态。这样在挂载到客户端应用程序之前,可以直接在store获取到内敛预置状态。
我们需要通过访问路由,来决定获取哪部分数据,所以在路由组件中放置数据预取逻辑。
服务端数据预取
我们要在组件中暴露一个asyncData方法,在服务端配置成如果组件暴露asyncData,就调用这个方法,然后将解析完的状态,附加到渲染上下文(render context)中。
router.onReady(() => {
const matchedComponents = router.getMatchedComponents()
if (!matchedComponents.length) {
return reject({ code: 404 })
}
// 对所有匹配的路由组件调用 `asyncData()`
Promise.all(matchedComponents.map(Component => {
if (Component.asyncData) {
return Component.asyncData({
store,
route: router.currentRoute
})
}
})).then(() => {
context.state = store.state
resolve(app)
}).catch(reject)
当使用template时,context.state将作为window.__INITAIL_STATE__状态,自动嵌入到HTML中,在挂载到应用程序之前,store就应该获取到状态:
// entry-client.js
const { app, router, store } = createApp()
if (window.__INITIAL_STATE__) {
store.replaceState(window.__INITIAL_STATE__)
}
客户端数据预取
当使用template时,context.state将作为window.__INITAIL_STATE__状态,自动嵌入到HTML中,在挂载到应用程序之前,store就应该获取到状态:
1. 在beforeMount 时候获取数据:
Vue.mixin({
beforeMount () {
const { asyncData } = this.$options
if (asyncData) {
// 将获取数据操作分配给 promise
// 以便在组件中,我们可以在数据准备就绪后
// 通过运行 `this.dataPromise.then(...)` 来执行其他任务
this.dataPromise = asyncData({
store: this.$store,
route: this.$route
})
}
}
})
2.在路由导航前解析数据
// entry-client.js
router.onReady(() => {
router.beforeResolve((to, from, next) => {
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()
}
Promise.all(activated.map(c => {
if (c.asyncData) {
return c.asyncData({ store, route: to })
}
})).then(() => {
next()
}).catch(next)
})
app.$mount('#app')
})
以上两种策略在路由组件重用时,也应该调用asyncData函数:
Vue.mixin({
beforeRouteUpdate (to, from, next) {
const { asyncData } = this.$options
if (asyncData) {
asyncData({
store: this.$store,
route: to
}).then(next).catch(next)
} else {
next()
}
}
})
到这里数据预取就已经做完了~
愿我们有能力不向生活缴械投降---Lin