I have a requirement to showcase an image obtained from an external API. The image fetching logic is implemented in the mounted
hook of my ProductCard.vue
component.
<template>
<q-card
class="my-card column text-center no-border-radius"
flat
bordered
>
<q-img
:src="PRODUCT_IMG_SRC"
sizes="(max-width: 400px) 400w,
(min-width: 400px) and (max-width: 800px) 800w,
(min-width: 800px) and (max-width: 1200px) 1200w,
(min-width: 1200px) 1600w"
loading="eager"
/>
<q-card-section>
<div class="text-caption text-grey text-left">
{{ truncate(product.description, 100) }}
</div>
</q-card-section>
</q-card>
</template>
<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import { truncate } from 'src/utils/textUtils';
import fallback_image from 'src/assets/dluhopis_houses_responsive.svg';
export default defineComponent({
name: 'ProductCard',
props: {
product: Object,
chosen: Boolean,
},
setup(props) {
const PRODUCT_IMG_SRC = ref();
onMounted(async() => {
const IMG_URL = `https://ydc.datanasiti.cz/api/product/${props?.product?.externalId}/image`;
const response = await fetch(IMG_URL);
if (response.status === 200) {
return (PRODUCT_IMG_SRC.value = IMG_URL);
} else {
PRODUCT_IMG_SRC.value = fallback_image;
}
});
return {
truncate,
PRODUCT_IMG_SRC,
};
},
});
</script>
In the parent component, I use a v-for
loop to render this child component based on the computed property PageProducts
, which filters products per page.
<template>
<div
v-if="pageProducts"
:class="[productChosen ? '' : 'row items-stretch q-col-gutter-x-md']"
class="q-pb-md wrap"
>
<template v-if="!productChosen">
<div
v-for="(product, index) in pageProducts"
:key="`md-${index}`"
class="col-sm-5 col-md-4 col-lg-3 col-xl-2 q-mt-md justify-sm-center flex"
>
<product-card
:product="product"
@product-detail="toggleDetail"
@choose-product="chooseProduct"
/>
</div>
</template>
<div
class="q-pa-lg flex flex-center col-12"
>
<q-pagination
v-if="!productChosen"
v-model="currentPage"
:max="pagesCount()"
direction-links
/>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, onMounted, reactive, ref, toRefs, computed } from 'vue';
import ProductCard from 'src/components/ProductCard.vue';
import { products } from 'src/api/api';
import { AxiosResponse } from 'axios';
import useDate from 'src/utils/useDate';
import { useQuasar } from 'quasar';
import { IProduct, PAYOUT_FREQUENCY } from 'src/interfaces/Purchase';
// Component definition...
</script>
The issue I encountered is that the mounted
method in the child component ProductCard.vue
is not called for every product when the computed property changes in the parent component. It seems to only trigger for the first 8 products and then again when navigating between certain pages. This behavior is puzzling.
Any insights into why this occurs or suggestions on how to improve this behavior?