如何在数据加载完成之前处理 Vue 组件内容
How to handle Vue component content before data has finished loading
我正在将 Prismic 的一些产品类别数据加载到我的 Nuxt 项目中,我正在寻找有关最佳实践的一些说明。具体如何处理还在抓取数据,侧边栏没有内容可显示的状态。
现在,这是我的工作:
我有一个侧边栏组件 (Sidebar.vue
):
<template>
<div class="xl:flex-shrink-0 xl:w-64 border-r border-gray-200 pt-5 pb-4 bg-white overflow-y-auto ">
<h3 class="text-xl font-bold text-gray-800">{{ navigation.heading }}</h3>
<div class="mt-5 flex-grow flex flex-col">
<nav class="flex-1 px-2 space-y-1 bg-white" aria-label="Sidebar">
<div v-for="(category, index) in navigation.categories" :key="index">
<SidebarItem v-if="!category.subcategories.length" :category="category"/>
<SidebarSection v-else-if="category.subcategories.length" @click="toggleExpansion(index)" :category="category"/>
</div>
</nav>
</div>
</div>
</template>
<script lang="ts">
export default {
data() {
return {
navigation: new Navigation('Categories')
}
},
async mounted() {
const that = this
this.fetchCategories()
.then(function() {
that.navigation = that.$store.getters.navigation
})
},
methods: {
...mapActions({ fetchCategories: 'fetchCategories' })
}
}
</script>
如您所见,我有一个 navigation
属性,它将包含填充边栏所需的所有数据。目前,我已经初始化了一个占位符实例 (new Navigation('Categories')
),因为没有这个,Vue 报告 navigation
未定义。
感觉这不是解决此问题的理想方式。在不提供占位符实例的情况下,在加载数据之前处理此中间状态的最合适方法是什么?
Nuxt 的 fetch
hook 在这里可能会有用。它公开 $fetchState
(包括 pending
、error
和 timestamp
)以强制使用或在您的模板中使用。您的模板可以在呈现 navigation
数据之前检查 pending
标志:
<template>
<div v-if="!$fetchState.pending"
class="xl:flex-shrink-0 xl:w-64 border-r border-gray-200 pt-5 pb-4 bg-white overflow-y-auto">
<h3 class="text-xl font-bold text-gray-800">{{ navigation.heading }}</h3>
<div class="mt-5 flex-grow flex flex-col">
<nav class="flex-1 px-2 space-y-1 bg-white" aria-label="Sidebar">
<div v-for="(category, index) in navigation.categories" :key="index">
<SidebarItem v-if="!category.subcategories.length" :category="category"/>
<SidebarSection v-else-if="category.subcategories.length" @click="toggleExpansion(index)" :category="category"/>
</div>
</nav>
</div>
</div>
</template>
<script lang="ts">
export default {
// BEFORE:
// async mounted() {
// const that = this
// this.fetchCategories()
// .then(function() {
// that.navigation = that.$store.getters.navigation
// })
// },
// AFTER:
async fetch() {
await this.fetchCategories()
this.navigation = this.$store.getters.navigation
},
}
</script>
我正在将 Prismic 的一些产品类别数据加载到我的 Nuxt 项目中,我正在寻找有关最佳实践的一些说明。具体如何处理还在抓取数据,侧边栏没有内容可显示的状态。
现在,这是我的工作:
我有一个侧边栏组件 (Sidebar.vue
):
<template>
<div class="xl:flex-shrink-0 xl:w-64 border-r border-gray-200 pt-5 pb-4 bg-white overflow-y-auto ">
<h3 class="text-xl font-bold text-gray-800">{{ navigation.heading }}</h3>
<div class="mt-5 flex-grow flex flex-col">
<nav class="flex-1 px-2 space-y-1 bg-white" aria-label="Sidebar">
<div v-for="(category, index) in navigation.categories" :key="index">
<SidebarItem v-if="!category.subcategories.length" :category="category"/>
<SidebarSection v-else-if="category.subcategories.length" @click="toggleExpansion(index)" :category="category"/>
</div>
</nav>
</div>
</div>
</template>
<script lang="ts">
export default {
data() {
return {
navigation: new Navigation('Categories')
}
},
async mounted() {
const that = this
this.fetchCategories()
.then(function() {
that.navigation = that.$store.getters.navigation
})
},
methods: {
...mapActions({ fetchCategories: 'fetchCategories' })
}
}
</script>
如您所见,我有一个 navigation
属性,它将包含填充边栏所需的所有数据。目前,我已经初始化了一个占位符实例 (new Navigation('Categories')
),因为没有这个,Vue 报告 navigation
未定义。
感觉这不是解决此问题的理想方式。在不提供占位符实例的情况下,在加载数据之前处理此中间状态的最合适方法是什么?
Nuxt 的 fetch
hook 在这里可能会有用。它公开 $fetchState
(包括 pending
、error
和 timestamp
)以强制使用或在您的模板中使用。您的模板可以在呈现 navigation
数据之前检查 pending
标志:
<template>
<div v-if="!$fetchState.pending"
class="xl:flex-shrink-0 xl:w-64 border-r border-gray-200 pt-5 pb-4 bg-white overflow-y-auto">
<h3 class="text-xl font-bold text-gray-800">{{ navigation.heading }}</h3>
<div class="mt-5 flex-grow flex flex-col">
<nav class="flex-1 px-2 space-y-1 bg-white" aria-label="Sidebar">
<div v-for="(category, index) in navigation.categories" :key="index">
<SidebarItem v-if="!category.subcategories.length" :category="category"/>
<SidebarSection v-else-if="category.subcategories.length" @click="toggleExpansion(index)" :category="category"/>
</div>
</nav>
</div>
</div>
</template>
<script lang="ts">
export default {
// BEFORE:
// async mounted() {
// const that = this
// this.fetchCategories()
// .then(function() {
// that.navigation = that.$store.getters.navigation
// })
// },
// AFTER:
async fetch() {
await this.fetchCategories()
this.navigation = this.$store.getters.navigation
},
}
</script>