VueJS 2.0服务端渲染:如何使用preFetch和beforeRouteEnter只获取一次数据?
VueJS 2.0 server-side rendering: How to get data only once using preFetch and beforeRouteEnter?
为了测试 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')
中完成
也可以vue查看是否在服务器上
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()
}
},
您可以做的是在商店中设置一个变量,说明此页面的数据已加载。读取该变量以查看是否应调用 ajax 请求。
我已经想通了。我将使用 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()
}
}
我只是检查 window 对象是否在组件的 created
方法中定义:
created () {
if (typeof window === 'undefined') {
// we're in server side
} else {
// we're in the client
}
}
为了测试 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')
也可以vue查看是否在服务器上
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()
}
},
您可以做的是在商店中设置一个变量,说明此页面的数据已加载。读取该变量以查看是否应调用 ajax 请求。
我已经想通了。我将使用 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()
}
}
我只是检查 window 对象是否在组件的 created
方法中定义:
created () {
if (typeof window === 'undefined') {
// we're in server side
} else {
// we're in the client
}
}