Reputation: 11
I'm trying to show the list of products of different categories, which are retrieved from the server and cached, so when switching between categories, I don't have to make new requests every time. For that, I've used <keep-alive></keep-alive>
, and It works partially.
<template>
<div class="category">
<h3 class="title animate-charcter"
id="title">Choose the category</h3>
<div class="category-container">
<img class="category-item"
data-cat="woman"
@click="component = 'WomanClothes'"
src="@/assets/hmwlogo.png">
<img class="category-item"
data-cat="electronics"
@click="component = 'Electronics'"
src="@/assets/electrologo2.jpg">
<img class="category-item"
data-cat="furniture"
@click="component = 'Furniture'"
src="@/assets/furniturelogo.png">
<img class="category-item"
data-cat="man"
@click="component = 'ManClothes'"
src="@/assets/hmmlogo.png">
</div>
<keep-alive>
<component :is="component" />
</keep-alive>
</div>
</template>
<script>
import WomanClothes from "./WomanClothes.vue"
import Electronics from "./Electronics.vue"
import Furniture from "./Furniture.vue"
import ManClothes from "./ManClothes.vue"
export default {
name: "Category",
components: { WomanClothes , Electronics , Furniture , ManClothes },
data() {
return {
component: "WomanClothes"
}
},
}
</script>
So when the user clicks on one of the category items, <component :is="component" />
dynamically updates itself. 4 other components that I've imported do API call, retrieves the data, and dynamically shows the data. The code is the same (I know it's efficient), just use different endpoints. So I will just show the code for one of them:
WomanClothes.vue:
<template>
<div class="product-list-container">
<input />
<div class="row">
<div class="list-item-container"
v-for="product in products"
:key="product.productId"
@click="seeTheProduct(product)">
<img :src="product.images[0].paths[0]"
class="card-img-top"
loading="lazy"
alt="...">
<div class="card-info">
<h5 class="card-title">{{ product.name }}</h5>
<h5 class="card-price">{{ product.price }} $.</h5>
</div>
</div>
</div>
<div class="load-more">
<button v-if="loadMore"
v-show="loadNow"
@click="loadMoreProducts">
Load more
</button>
<p v-else>End of the page</p>
</div>
</div>
</template>
<script>
/* eslint-disable */
import { db } from '../firebase';
export default {
name: "Products-list",
props: {
msg: String
},
data() {
return {
products: [],
tempArr: [],
path: '',
latestDoc: null,
loadMore: true,
loadNow: true
}
},
created() {
console.log('from created')
this.getProducts('products/woman-id/w-items')
},
destroyed() {
console.log('on destroy')
},
methods: {
loadMoreProducts() {
this.loadNow = !this.loadNow;
this.latestDoc = this.$store.getters.getDocHMW
this.getProducts('products/woman-id/w-items')
},
async getProducts(category) {
this.tempArr = []
const ref = db.collection(category)
.orderBy('price')
.startAfter(this.latestDoc || 0)
.limit(12)
const data = await ref.get();
data.docs.forEach(doc => {
// this.tempArr.push(doc.data())
this.products.push(doc.data())
})
this.latestDoc = data.docs[data.docs.length - 1];
this.$store.commit('saveDoc', {doc: this.latestDoc, cat: 'hmw'})
if (data.empty) {
console.log('empty db')
this.loadMore = false;
this.$store.commit('saveBtnStatus', this.loadMore)
}
this.loadNow = true
},
// function to route to product info page
seeTheProduct(product) {
// saving to vuex and in localStorage
this.$store.commit('checkProduct', product)
// redirect the page
this.$router.push({
name: 'productinfo'
})
}
},
};
</script>
When seeTheProduct
function gets called, the destroyed
hook gets called, which means all cached data gets lost, when back to that route again. How can I make it, so when the route is being changed, the component which called for route change, doesn't get destroyed ?
Upvotes: 1
Views: 1629
Reputation: 21
I believe you need to specify the 'key' prop on the router-view, like this:
<router-view :key="$route.fullPath"></router-view>
Then the keep-alive component will cache each component by key which evaluates to the url.
Upvotes: 2