Nuxt static 在推送新路由时不加载获取的状态
Nuxt static not loading fetched state when pushing new route
我正在按照此处所述使用 nuxt 生成完整的静态 Web 应用 https://nuxtjs.org/blog/going-full-static/#crazy-fast-static-applications
我还有一个小博客要作为静态站点加载,所以我使用获取挂钩从 api 加载数据。
async fetch() {
this.posts = await fetch(`${this.baseApi}/posts`).then(res => res.json())
},
当我生成(npm run generate
)时,获取的状态在dist/assets/static
内部正确生成,所以当直接访问/blog
时,状态被正确加载并且数据正确显示.
但是,当我进入主页并使用
访问博客时
this.$router.push
或一个
<nuxt-link to="/blog">Blog</nuxt-link>
获取的状态没有加载,我必须再次调用 api,或者在 mounted()
钩子中再调用一次 this.$fetch()
我已经添加了一个
watch: {
'$route.query': '$fetch'
}
到首页
我需要在使用导航时正确加载获取的状态我还缺少什么?
澄清
我没有遇到任何关于获取挂钩本身的问题,而是导航没有检索目标路线的状态。
甚至 HTML 也在那里
我需要页面获取目标路由的状态,当路由发生变化时,因为vue模板依赖它,所以如果没有加载,ui不会显示任何东西,我被迫手动调用获取挂钩
为了看得更清楚,这是直接访问 /blog 时我的开发工具的屏幕截图,请注意如何正确检索 state.js(它包含所有呈现的内容)
下面是我的devtools访问/的截图,然后使用nuxt-link或this.$router.push(同样的结果)
静态截图:
Blog.vue
<template>
<b-container class="container blog">
<b-row>
<b-col lg="12" md="12" sm="12" cols="12" class="logo-col">
<SbLogoSingle />
</b-col>
</b-row>
<b-row v-if="$fetchState.pending" class="text-center">
<b-spinner style="margin: auto"></b-spinner>
</b-row>
<b-row v-else>
<b-col
v-for="(post, idx) in posts.data"
:key="idx"
lg="4"
md="4"
sm="6"
cols="12"
class="blog-post-col"
>
<b-card
v-if="post !== undefined"
no-body
class="shadow-lg blog-post-card"
:img-src="post.media.url"
img-top
>
<b-card-body class="text-left">
<b-card-title>{{ replaceSlugByString(post.slug) }}</b-card-title>
<b-card-text
class="post-short-description"
v-html="post.localizations[0].shortDescription"
></b-card-text>
</b-card-body>
<template #footer>
<div class="text-left">
<b-button class="apply-btn read-more-btn" @click="openBlogPost(idx)">Read more</b-button>
</div>
</template>
</b-card>
</b-col>
</b-row>
</b-container>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
slug: 'test',
posts: {},
currentPage: 1,
perPage: 12,
pageIndex: 1,
totalPages: 1,
}
},
async fetch() {
const response = await fetch(`${this.baseApi}/StaticPage`)
const fetchedPosts = await response.json()
this.posts = fetchedPosts
// this.posts = await fetch(`${this.baseApi}/StaticPage`).then(res =>res.json())
},
computed: {
...mapState('modules/settings', ['baseApi']),
},
beforeMount() {
this.$fetch() // i want to remove this because the pages are statically generated correctly, I'm only adding it to refresh the state. which can be retrieved as a separate js file when accessing the route directly
},
methods: {
openBlogPost(idx) {
const pageObject = this.posts.data[idx]
this.$router.push({
name: `blog-slug`,
params: {
slug: pageObject.slug,
page: pageObject,
},
})
},
replaceSlugByString(slug) {
return slug.replaceAll('-', ' ')
},
},
}
</script>
这是 slug.vue
的 pastebin
编辑:
fetch()
钩子很好用,即使你第一次来到这个特定页面,它也会被触发
- Vue devtools 可以帮助您找出是否有某些状态缺失或行为异常。
- 静态文件夹中没有 状态这样的东西 因为状态根本不是静态变量或事物,它是动态的并且仅在运行时可用。
- 这个答案可能会帮助您看到一个使用 JSONplaceholder 的工作示例(带有列表 + 详细信息页面):
尽量不要混用 async/await
和 then
。
所以,这种语法应该更适合。
async fetch() {
const response = await fetch(`${this.baseApi}/posts`)
const fetchedPosts = await response.json()
console.log('posts', fetchedPosts)
this.posts = fetchedPosts
},
然后,你可以通过devtools的网络选项卡进行调试,看看是否触发了。不过我觉得到时候应该没问题。
我刚刚写得更深入的这个答案也可以帮助更多地理解 fetch()
钩子:
使用 nuxt generate
使用 nuxt 生成静态网站时,您使用 fetch hook 加载一次数据,而无需在您的站点中再次加载它。
您可能会遇到这样一种情况,您有一个正确生成的 html 页面,但数据为空,即使您可以在 html 源中看到内容,而空数据会导致UI 不加载,并强制您重新点击 api(或手动调用 $fetch
挂钩),以重新加载您的状态(和您的 UI)
在这种情况下,将您的数据移动到商店,在我的情况下,我创建了一个新的 store/modules/blog.js
文件:
export const state = () => ({
posts:[]
})
export const mutations = {
SET_POSTS(state, posts) {
state.posts = posts
}
}
然后修改你的 fetch hook 为:
async fetch() {
const response = await this.$axios.$get(`${this.baseApi}/posts`)
this.$store.commit("modules/blog/SET_POSTS",response)
}
你可以把this.$axios丢掉,用fetch也没关系。
然后,在你 运行 npm run generate
之后,看看你的 dist/assets/static/<someid>/state.js
你会发现里面有主页的所有状态(我的主页不包括博客文章)所以我读了 modules:{blog:{posts:[]}...
empty array
转到您的 dist/assets/static/<someid>/blog/state.js
,您应该会在 modules:{blog:{posts:{success:am,code:an ...
中找到从 api 加载的所有帖子
还有一个dist/assets/static/<someid>/blog/payload.js
现在,当您访问您的主页时,当 <nuxt-link to='/blog'>
可见时将获取博客的 payload.js
,并且您的状态将使用已获取的数据进行更新
现在,如果您直接访问 /blog
,将在获取 payload.js
之前检索 state.js
,您的状态将是最新的
这就是您创建一个小型静态博客的方式,而无需点击 API。希望这对您有所帮助。
我正在按照此处所述使用 nuxt 生成完整的静态 Web 应用 https://nuxtjs.org/blog/going-full-static/#crazy-fast-static-applications
我还有一个小博客要作为静态站点加载,所以我使用获取挂钩从 api 加载数据。
async fetch() {
this.posts = await fetch(`${this.baseApi}/posts`).then(res => res.json())
},
当我生成(npm run generate
)时,获取的状态在dist/assets/static
内部正确生成,所以当直接访问/blog
时,状态被正确加载并且数据正确显示.
但是,当我进入主页并使用
this.$router.push
或一个
<nuxt-link to="/blog">Blog</nuxt-link>
获取的状态没有加载,我必须再次调用 api,或者在 mounted()
钩子中再调用一次 this.$fetch()
我已经添加了一个
watch: {
'$route.query': '$fetch'
}
到首页
我需要在使用导航时正确加载获取的状态我还缺少什么?
澄清
我没有遇到任何关于获取挂钩本身的问题,而是导航没有检索目标路线的状态。 甚至 HTML 也在那里 我需要页面获取目标路由的状态,当路由发生变化时,因为vue模板依赖它,所以如果没有加载,ui不会显示任何东西,我被迫手动调用获取挂钩
为了看得更清楚,这是直接访问 /blog 时我的开发工具的屏幕截图,请注意如何正确检索 state.js(它包含所有呈现的内容)
下面是我的devtools访问/的截图,然后使用nuxt-link或this.$router.push(同样的结果)
静态截图:
Blog.vue
<template>
<b-container class="container blog">
<b-row>
<b-col lg="12" md="12" sm="12" cols="12" class="logo-col">
<SbLogoSingle />
</b-col>
</b-row>
<b-row v-if="$fetchState.pending" class="text-center">
<b-spinner style="margin: auto"></b-spinner>
</b-row>
<b-row v-else>
<b-col
v-for="(post, idx) in posts.data"
:key="idx"
lg="4"
md="4"
sm="6"
cols="12"
class="blog-post-col"
>
<b-card
v-if="post !== undefined"
no-body
class="shadow-lg blog-post-card"
:img-src="post.media.url"
img-top
>
<b-card-body class="text-left">
<b-card-title>{{ replaceSlugByString(post.slug) }}</b-card-title>
<b-card-text
class="post-short-description"
v-html="post.localizations[0].shortDescription"
></b-card-text>
</b-card-body>
<template #footer>
<div class="text-left">
<b-button class="apply-btn read-more-btn" @click="openBlogPost(idx)">Read more</b-button>
</div>
</template>
</b-card>
</b-col>
</b-row>
</b-container>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
slug: 'test',
posts: {},
currentPage: 1,
perPage: 12,
pageIndex: 1,
totalPages: 1,
}
},
async fetch() {
const response = await fetch(`${this.baseApi}/StaticPage`)
const fetchedPosts = await response.json()
this.posts = fetchedPosts
// this.posts = await fetch(`${this.baseApi}/StaticPage`).then(res =>res.json())
},
computed: {
...mapState('modules/settings', ['baseApi']),
},
beforeMount() {
this.$fetch() // i want to remove this because the pages are statically generated correctly, I'm only adding it to refresh the state. which can be retrieved as a separate js file when accessing the route directly
},
methods: {
openBlogPost(idx) {
const pageObject = this.posts.data[idx]
this.$router.push({
name: `blog-slug`,
params: {
slug: pageObject.slug,
page: pageObject,
},
})
},
replaceSlugByString(slug) {
return slug.replaceAll('-', ' ')
},
},
}
</script>
这是 slug.vue
的 pastebin编辑:
fetch()
钩子很好用,即使你第一次来到这个特定页面,它也会被触发- Vue devtools 可以帮助您找出是否有某些状态缺失或行为异常。
- 静态文件夹中没有 状态这样的东西 因为状态根本不是静态变量或事物,它是动态的并且仅在运行时可用。
- 这个答案可能会帮助您看到一个使用 JSONplaceholder 的工作示例(带有列表 + 详细信息页面):
尽量不要混用 async/await
和 then
。
所以,这种语法应该更适合。
async fetch() {
const response = await fetch(`${this.baseApi}/posts`)
const fetchedPosts = await response.json()
console.log('posts', fetchedPosts)
this.posts = fetchedPosts
},
然后,你可以通过devtools的网络选项卡进行调试,看看是否触发了。不过我觉得到时候应该没问题。
我刚刚写得更深入的这个答案也可以帮助更多地理解 fetch()
钩子:
使用 nuxt generate
使用 nuxt 生成静态网站时,您使用 fetch hook 加载一次数据,而无需在您的站点中再次加载它。
您可能会遇到这样一种情况,您有一个正确生成的 html 页面,但数据为空,即使您可以在 html 源中看到内容,而空数据会导致UI 不加载,并强制您重新点击 api(或手动调用 $fetch
挂钩),以重新加载您的状态(和您的 UI)
在这种情况下,将您的数据移动到商店,在我的情况下,我创建了一个新的 store/modules/blog.js
文件:
export const state = () => ({
posts:[]
})
export const mutations = {
SET_POSTS(state, posts) {
state.posts = posts
}
}
然后修改你的 fetch hook 为:
async fetch() {
const response = await this.$axios.$get(`${this.baseApi}/posts`)
this.$store.commit("modules/blog/SET_POSTS",response)
}
你可以把this.$axios丢掉,用fetch也没关系。
然后,在你 运行 npm run generate
之后,看看你的 dist/assets/static/<someid>/state.js
你会发现里面有主页的所有状态(我的主页不包括博客文章)所以我读了 modules:{blog:{posts:[]}...
empty array
转到您的 dist/assets/static/<someid>/blog/state.js
,您应该会在 modules:{blog:{posts:{success:am,code:an ...
中找到从 api 加载的所有帖子
还有一个dist/assets/static/<someid>/blog/payload.js
现在,当您访问您的主页时,当 <nuxt-link to='/blog'>
可见时将获取博客的 payload.js
,并且您的状态将使用已获取的数据进行更新
现在,如果您直接访问 /blog
,将在获取 payload.js
之前检索 state.js
,您的状态将是最新的
这就是您创建一个小型静态博客的方式,而无需点击 API。希望这对您有所帮助。