前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue SSR ---数据预取和状态

Vue SSR ---数据预取和状态

作者头像
用户3258338
发布2019-08-09 16:41:45
1.3K0
发布2019-08-09 16:41:45
举报

没有结局的故事太多,你要习惯相遇和离别~

哈喽,宝宝们,已经到八月了呢,9012将近过去三分之二,赶紧看看今年的计划是否正常进行~

speak is cheap !

上篇文章中我们已经学习了如何把vue实例渲染成HTML字符串,还有一个重要的问题:我们的程序中,大部分都是需要获取数据,所以获取数据是灰常重要的。接下来我们看一下要怎么获取数据~

数据预取存储容器

在服务端渲染之前我们就要获取到数据,否则服务端渲染的意义就不存在了。所以在之前需要先预取和解析好这些数据。

另外,在挂载到应用程序之前,需要获取与服务端相同的数据,否则会导致混合失败。

所以,获取的数据需要在视图组件之外,即放置在专门的数据预取存储容器中。

首先,在服务端渲染之前预取数据,并将数据填充到store。此外在HTML中序列化和内联预置状态。这样在挂载到客户端应用程序之前,可以直接在store获取到内敛预置状态。

我们需要通过访问路由,来决定获取哪部分数据,所以在路由组件中放置数据预取逻辑。

服务端数据预取

我们要在组件中暴露一个asyncData方法,在服务端配置成如果组件暴露asyncData,就调用这个方法,然后将解析完的状态,附加到渲染上下文(render context)中。

代码语言:javascript
复制
    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就应该获取到状态:

代码语言:javascript
复制
// 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 时候获取数据:

代码语言:javascript
复制
Vue.mixin({
  beforeMount () {
    const { asyncData } = this.$options
    if (asyncData) {
      // 将获取数据操作分配给 promise
      // 以便在组件中,我们可以在数据准备就绪后
      // 通过运行 `this.dataPromise.then(...)` 来执行其他任务
      this.dataPromise = asyncData({
        store: this.$store,
        route: this.$route
      })
    }
  }
})

2.在路由导航前解析数据

代码语言:javascript
复制
// 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函数:

代码语言:javascript
复制
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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 女程序员的日常 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档