mys*_*ore 5 server-side-rendering nuxt.js ssg
我正在使用 nuxt 生成完整的静态 Web 应用程序,如下所述https://nuxtjs.org/blog/going-full-static/#crazy-fast-static-applications
我有一个小博客也可以作为静态站点加载,因此我使用 fetch hook 从 api 加载数据。
async fetch() {
this.posts = await fetch(`${this.baseApi}/posts`).then(res => res.json())
},
Run Code Online (Sandbox Code Playgroud)
当我生成( npm run generate)时,获取的状态在内部正确生成dist/assets/static,因此当直接访问时/blog,状态被正确加载并且数据显示正确。但是,当我在主页上并使用访问博客时
this.$router.push
Run Code Online (Sandbox Code Playgroud)
或一个
<nuxt-link to="/blog">Blog</nuxt-link>
Run Code Online (Sandbox Code Playgroud)
获取到的状态没有加载,我必须再次调用api,或者在钩子中再调用this.$fetch()一次mounted()
我已经添加了一个
watch: {
'$route.query': '$fetch'
}
Run Code Online (Sandbox Code Playgroud)
到主页
使用导航时我需要正确加载获取的状态我还缺少什么?
澄清
我没有遇到 fetch hook 本身的任何问题,而是导航没有检索目标路由的状态。即使HTML在那里我也需要页面来获取目标路由的状态,当路由发生变化时,因为vue模板依赖于它,所以如果它没有加载,ui将不会显示任何内容,我被迫手动调用 fetch hook
为了更清晰的视图,这是我的开发工具在直接访问 /blog 时的屏幕截图,请注意如何正确检索 state.js(它包含所有渲染的内容)

以下是我的开发工具在访问 / 时的屏幕截图,然后使用 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>
Run Code Online (Sandbox Code Playgroud)
这是 slug.vue 的 Pastebin
当使用 nuxt using 生成静态网站时nuxt generate,您可以使用 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
}
}
Run Code Online (Sandbox Code Playgroud)
然后将您的 fetch 挂钩修改为:
async fetch() {
const response = await this.$axios.$get(`${this.baseApi}/posts`)
this.$store.commit("modules/blog/SET_POSTS",response)
}
Run Code Online (Sandbox Code Playgroud)
您可以丢弃 this.$axios,并使用 fetch 并不重要。
然后,运行后npm run generate,看看你的,dist/assets/static/<someid>/state.js你会发现里面有主页的所有状态(我的主页不包括博客文章),所以我读了modules:{blog:{posts:[]}...空数组
转到您的dist/assets/static/<someid>/blog/state.js,您应该会发现从那里的 api 加载的所有帖子modules:{blog:{posts:{success:am,code:an ...
还有一个dist/assets/static/<someid>/blog/payload.js
现在,当您访问主页时,payload.js博客的<nuxt-link to='/blog'>变得可见时将被提取,并且您的状态将使用已提取的数据进行更新
现在,如果您直接访问/blog将state.js在提取之前检索payload.js,并且您的状态将是最新的
这就是您无需使用 API 即可创建小型静态博客的方法。希望这有帮助。
| 归档时间: |
|
| 查看次数: |
5524 次 |
| 最近记录: |