VueJS 2.0服务器端呈现:如何使用preFetch和beforeRouteEnter只获取一次数据?

时间:2017-01-11 09:11:56

标签: javascript vuejs2 vue.js serverside-rendering

为了测试VueJS服务器边缘渲染,我试图解决一些问题。我已经使用最新的VueJS Hackernews 2.0作为此项目的样板。

目前我坚持这个:

服务器使用preFetch预取数据。都好。 当用户路由到此组件时,在beforeRouteEnter函数内调用相同的函数。一切都好。

但是,当用户第一次加载时,preFetchData函数会被调用2次。进入preFetch后进入beforeRouteEnter

这是有道理的,因为这就是Vue路由器的工作原理。 preFetch在服务器上运行,只要Vue在客户端中呈现,beforeRouteEnter就会被调用。

但是,我不希望Vue在第一次加载时执行此操作2次,因为数据已经从服务器端呈现函数preFetch存储在商店中。

我无法检查数据是否已存储在商店中,因为我希望该组件始终在beforeRouteEnter上进行API调用。当它第一次从服务器上呈现时,就不会了。

如何在此上下文中仅获取一次数据?

  <template>
    <div class="test">
        <h1>Test</h1>
      <div v-for="item in items">
        {{ item.title }}
      </div>
    </div>
  </template>

  <script>
  import store from '../store'

  function preFetchData (store) {
    return store.dispatch('GET_ITEMS')
  }

  export default {
    beforeRouteEnter (to, from, next) {
      // We only want to use this when on the client, not the server
      // On the server we have preFetch
      if (process.env.VUE_ENV === 'client') {
        console.log('beforeRouterEnter, only on client')
        preFetchData(store)
        next()
      } else {
        // We are on the server, just pass it
        next()
      }
    },
    name: 'test',
    computed: {
      items () {
        return this.$store.state.items
      }
    },
    preFetch: preFetchData // Only on server
  }
  </script>

  <style lang="scss">
  .test {
    background: #ccc;
    padding: 40px;

    div {
      border-bottom: 1px red solid;
    }
  }
  </style>

在上面:API调用在store.dispatch('GET_ITEMS')

中完成

4 个答案:

答案 0 :(得分:3)

我已经想出了什么。我将使用from.name检查用户来自哪里。如果这是null,则表示用户第一次加载页面,因为我命名了所有路由。因此,我们知道我们正在为服务器渲染HTML提供服务:

beforeRouteEnter (to, from, next) { 
    if (from.name && process.env.VUE_ENV === 'client') {
      preFetchData(store).then(data => {
        next(vm => {
          // do something
        })
      })
    } else {
      next()
    }
  }

答案 1 :(得分:0)

您也可以查看是否在服务器上。

this.$isServer

Vue.prototype.$isServer

如果您是本地人,则只调用您的beforeRouteEnter预取。

beforeRouteEnter(to, from, next) {
    // We only want to use this when on the client, not the server
    // On the server we have preFetch
    if (!this.$isServer) {
        console.log('beforeRouterEnter, only on client')
        preFetchData(store)
        next()
    } else {
        // We are on the server, just pass it
        next()
    }
},

答案 2 :(得分:0)

你可以做什么在商店设置一个变量,说明这个页面的数据已经加载了。读取该变量以查看是否应该调用ajax请求。

答案 3 :(得分:0)

我只是检查窗口对象是否在组件的created方法中定义:

created () {
  if (typeof window === 'undefined') {
    // we're in server side
  } else {
    // we're in the client
  }
}