Vue:检查图像是否已加载,如果未加载,则显示 backbone 加载器

du7egjpx  于 2023-11-21  发布在  Vue.js
关注(0)|答案(1)|浏览(238)

我需要检查浏览器是否加载了图像,是否获取了所有数据,然后显示内容,如果没有,则显示<ItemCardSkeleton />组件。因此,如果一个图像加载速度比其他图像快,我会想要显示内容,其余图像将有一个 backbone ,直到它们一个接一个地完全加载。
这里我传递isLoaded并使用v-model监听自定义事件update:isLoaded。为了检查图像是否加载,我使用@load事件并将$emit('update:isLoaded', true)分配给它。然后我在父组件<template v-if="storeRecipes.pending || isLoaded === false">中使用v-if来检查数据或图像是否加载。
问题:如果我重新加载页面,我可以看到 backbone 加载器,但它在加载图像之前消失在每张卡上。这意味着它只在数据挂起时显示,而不是在加载图像时显示。有什么想法吗?
父组件ItemSwiper.vue:

<template>
    <Swiper
        class="swiper"
        :breakpoints="swiperOptions.breakpoints"
        :pagination="{
            clickable: true,
        }"
        :loop="true"
        :modules="swiperOptions.modules">
        <template v-if="storeRecipes.pending || isLoaded === false">
            <SwiperSlide class="swiper__slide" v-for="item in 3" :key="item">
                <ItemCardSkeleton />
            </SwiperSlide>
        </template>
        <template v-else>
            <template v-for="recipe in storeRecipes.data" :key="recipe.id">
                <SwiperSlide class="swiper__slide">
                    <ItemCard :data="recipe" v-model:isLoaded="isLoaded" />
                </SwiperSlide>
                <div class="swiper-custom-pagination"></div>
            </template>
        </template>
    </Swiper>
</template>

<script setup>
import { onMounted, ref } from 'vue';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Pagination } from 'swiper/modules';
import 'swiper/css/free-mode';
import 'swiper/css/pagination';
import 'swiper/css';
import { useStoreRecipes } from '@/stores/recipes/storeRecipes.js';

import ItemCard from '@/components/ItemCard.vue';
import ItemCardSkeleton from '@/components/SkeletonLoaders/ItemCardSkeleton.vue';

const storeRecipes = useStoreRecipes();
const isLoaded = ref();
  
onMounted(() => {
    storeRecipes.loadRecipes();
});
</script>

字符串
子组件ItemCard.vue:

<template>
    <div class="card">
        <div class="card__item">
            <img
                class="card__image"
                @load="$emit('update:isLoaded', true)"
                :src="getSrc('.jpg')"
                :alt="data.alt"/>
            <div class="card__content">
                <h2 class="card__title">{{ data.title }}</h2>
                <p class="card__text">{{ data.text }}</p>
                <router-link class="card__link" :to="{ name: 'Home' }"
                    >View more</router-link
                >
            </div>
        </div>
    </div>
</template>

<script setup>
const props = defineProps(['data', 'isLoaded']);
const emit = defineEmits(['update:isLoaded']);

const getSrc = ext => {
    return new URL(
        `../assets/images/recipe/${props.data.image}${ext}`,
        import.meta.url
    ).href;
};
</script>


全球商店:

export const useStoreRecipes = defineStore('storeRecipes', {
    state: () => {
        return {
            data: [],
            pending: false,
        };
    },
    actions: {
        async loadRecipes() {
            try {
                this.pending = true;
                const res = await fetch('/api/recipe');
                if (res.ok) {
                    const data = await res.json();
                    this.data = data;
                } else {
                    console.error('Error: ', res.status, res.statusText);
                }
            } catch (err) {
                console.error(err);
            } finally {
                this.pending = false;
            }
        },
    },
});

taor4pac

taor4pac1#

调用ref()而不使用任何初始参数意味着undefined
所以isLoaded === false比较等于undefined === false,返回false而不是true
你应该做:const isLoaded = ref(false)
额外:这有助于澄清您在评论中期望的内容

// your ItemCard.vue
<script setup>
    // pending now is a prop and you pass `storeRecipes.pending` here
    const props = defineProps(['data', 'isLoaded', 'pending']);
    const isLoaded = ref(false)
</script>

<template>
    <img v-if="pending || isLoaded" .... />
    <div v-else>This div is just example of what you had inside ItemCardSkeleton</div>
</template>

字符串
请注意:代码只是一个例子,你用你的源模板替换它们

相关问题