#javascript #vue.js #nuxt.js
#javascript #vue.js #nuxt.js
Вопрос:
У меня есть компонент с именем ProductArea
, который отображает продукты, загруженные из Prismic API
. Загружаемые продукты зависят от a category
, который выбирается пользователем на боковой панели.
Я использую Vuex
и изо всех сил пытаюсь создать поток, который позволяет избежать ситуации, когда category
он еще недоступен в моем хранилище ( category
также загружается из Prismic
).
Вот как ProductArea
выглядит родительский элемент:
<template>
<div>
<NavBar />
<!-- <Header /> -->
<main>
<div v-if="!$fetchState.pending" class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex-1 min-w-0 bg-white xl:flex">
<Sidebar :navigation="navigation" />
<ProductArea />
</div>
</div>
</main>
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import NavBar from '@/components/NavBar.vue'
import Sidebar from '@/components/Sidebar.vue'
import Header from '@/components/Header.vue'
import CategoryHeader from '@/components/CategoryHeader.vue'
import ProductGrid from '@/components/ProductGrid.vue'
import { mapActions } from 'vuex'
import { mapGetters } from 'vuex'
export default {
name: 'App',
components: {
Sidebar,
NavBar,
Header,
CategoryHeader
},
data() {
return {
navigation: null
}
},
async fetch() {
const component = this
await this.fetchCategories()
.then(function(navigationResult) {
const navigation = component.$store.getters.navigation
component.navigation = navigation
})
},
fetchOnServer: true,
methods: {
...mapActions({ fetchCategories: 'fetchCategories', fetchProducts: 'fetchProducts' })
}
}
</script>
Я предполагал v-if="!$fetchState.pending"
, что наличие ProductArea
предотвратит создание до category
тех пор, пока оно не будет загружено в хранилище, однако, похоже, это не так.
Вот ProductArea
:
<template>
<div class="bg-white lg:min-w-0 lg:flex-1">
<CategoryHeader :category="this.category" :products="this.products" />
<div class="sm:p-6">
<ProductGrid :category="this.category.primary.category" :products="this.products" />
</div>
</div>
</template>
<script lang="ts">
import { mapActions } from 'vuex'
import { mapGetters } from 'vuex'
import Locale from '@/types/locale'
export default {
name: 'ProductArea',
data() {
return {
category: this.$store.getters.category,
products: Array
}
},
async fetch() {
const component = this
await this.fetchProducts(this.category)
.then(function(productsResult) {
const products = component.$store.getters.products
component.products = products
console.log(products)
})
},
fetchOnServer: true,
methods: {
...mapActions({ fetchProducts: 'fetchProducts' })
}
}
</script>
Вот ошибка, которую я получаю:
Ошибка в fetch(): ошибка типа: не удается прочитать свойство ‘products’ неопределенного
Эта ошибка относится к неопределенному category
внутри fetchProducts
вызываемого via fetch
в ProductsArea
компоненте.
Кто-нибудь может указать мне правильное направление? Каков был бы оптимальный поток здесь, чтобы предотвратить category
доступ к нему до его доступности?
Ответ №1:
Вы можете установить категорию по умолчанию. Если вы не хотите этого делать, перенесите Vuex category
в родительский файл и показывайте его только <ProductArea>
тогда, когда он определен:
Родительский
<ProductArea v-if="category" />
computed: {
...mapGetters(['category'])
}
Это необходимо, потому что ваш v-if
on $fetchState.pending
проверяет только, загружены ли все категории, но для дочернего компонента вам также необходимо проверить, что a category
был выбран.
Фактически, вы можете упростить весь свой код, сопоставив геттеры вместо хранения геттеров в переменных, что не является хорошей практикой. Эти переменные не будут обновляться реактивно при изменении средства получения. Вместо этого полностью удалите data
параметры из обоих компонентов:
Родительский
async fetch() {
await this.fetchCategories();
}
computed: {
...mapGetters(['category', 'navigation'])
}
Дочерний элемент
async fetch() {
await this.fetchProducts();
}
computed: {
...mapGetters(['category', 'products'])
}
Другие улучшения:
- Вы можете немного сократить
mapActions
вызовы:Родительский:
...mapActions(['fetchCategories'])
Дочерний элемент:
...mapActions(['fetchProducts'])
Комментарии:
1. Отлично, спасибо. Есть пара других проблем с моим текущим кодом, которые означают, что я пока не могу это протестировать, но ясность в отношении лучших практик / что работает / что нет и т.д. — это то, что я искал. 👍