I have this ecommerce mock app in Vue and Vuex. This page shows a list of phones and there is a filter which filters phones based on the phone brands through checkboxes.
The problem is the page doesn't refresh straight away after I click the checkbox to filter. If I click another page and click back to the original page, then the page gets filtered.
The is my source code. Some code is removed for brevity.
Product.vue
import { mapActions } from "vuex"; import BrandFilter from "../components/BrandFilter"; export default { data() { return { products: this.$store.getters.filterProducts }; }, components: { BrandFilter } };
<template> <div class="container"> <div class="row"> <div class="col-lg-3"><BrandFilter></BrandFilter></div> <div class="col-lg-9"> <div class="row"> <div v-for="product in products":key="product.id"> <h4 class="card-title product__title"> {{ product.title }} </h4> </div> </div> </div> </div> </div> </template>
BrandFilter.vue
export default { name: "BrandFilter", data() { return { brands: this.$store.state.brands }; }, methods: { onChangeSelectBox(e) { debugger; const name = e.target.name; const value = e.target.checked; if (value) { this.$store.commit("addBrandToFilter", name); } else { this.$store.commit("removeBrandFromFilter", name); } } } };
<template> <div class="card mb-3"> <div class="card-header"> <h3>Brands</h3> </div> <ul class="list-group flex-row flex-wrap"> <li class="list-group-item flex-50" v-for="brand in brands":key="brand"> <label class="custom-checkbox text-capitalize"> {{ brand }} <input type="checkbox":name="brand" class="custom-checkbox__input" @input="onChangeSelectBox($event)" /> <span class="custom-checkbox__span"></span> </label> </li> </ul> </div> </template>
store/index.js
import Vue from "vue"; import Vuex from "vuex"; import { phones } from "../data/phones"; import { brands } from "../data/brands"; import { brandFilter } from "../filters/brandFilter"; Vue.use(Vuex); export default new Vuex.Store({ strict: true, state: { products: phones, brands: brands, cart: [], brandFilter: "" }, getters: { filterProducts(state) { debugger; const brands = state.brandFilter; const filterByBrandArr = brandFilter(state.products, brands); return filterByBrandArr; } }, mutations: { addBrandToFilter: (state, brand) => { debugger; if (state.brandFilter.includes(brand)) return void 0; state.brandFilter += brand; }, removeBrandFromFilter: (state, brand) => { debugger; const reg = new RegExp(brand, "gi"); state.brandFilter = state.brandFilter.replace(reg, ""); } } });
When you set a data item to a getter in Product.vue , it gets assigned only once. If the getter changes, the data doesn't change with it:
data() {
return {
products: this.$store.getters.filterProducts // ❌ Incorrect
}
}
Use a computed instead with mapGetters
to keep the component data synced with the Vuex data:
import { mapGetters } from 'vuex';
computed: {
...mapGetters(['filterProducts']) // ✅ Correct
}
Change your template to use that computed:
<div v-for="product in filterProducts" :key="product.id">
<h4 class="card-title product__title">
{{ product.title }}
</h4>
</div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.