javascript - Vue 组件不会重新加载 getter 数据(非响应式(Reactive))

标签 javascript vue.js vuejs2 vue-component vuex

我在 Vue 和 Vuex 中有这个电子商务模拟应用程序。此页面显示手机列表,并且有一个过滤器,可以通过复选框根据手机品牌过滤手机。

问题是我单击复选框进行过滤后,页面没有立即刷新。如果我单击另一个页面并单击返回原始页面,则该页面将被过滤。

enter image description here

这是我的源代码。为了简洁起见,删除了一些代码。

产品.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>

品牌过滤器.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>

商店/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, "");
    }
  }
});

最佳答案

当您在 Product.vue 中将数据项设置为 getter 时,它只会被分配一次。如果 getter 改变,数据不会随之改变:

data() {
  return {
    products: this.$store.getters.filterProducts  // ❌ Incorrect
  }
}

使用计算代替 mapGetters 来保持组件数据与 Vuex 数据同步:

import { mapGetters } from 'vuex';
computed: {
  ...mapGetters(['filterProducts'])  // ✅ Correct
}

更改您的模板以使用计算得出的:

<div v-for="product in filterProducts" :key="product.id">            
   <h4 class="card-title product__title">
      {{ product.title }}
   </h4>                            
</div>

关于javascript - Vue 组件不会重新加载 getter 数据(非响应式(Reactive)),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65588601/

相关文章:

javascript - 如何循环遍历数组并创建带有类别的术语表列表

css - Vuetify v-carousel 箭头重叠问题

javascript - v-for 中的 Vue 动态 v-model

jquery - 当Jquery更改文本输入时,Vuejs如何强制v-model更新?

javascript - 有没有办法将 Vuex 添加到 Vue 插件安装功能并在其组件之间共享状态?

vue.js - Pinia:使用设置语法时的 $reset 替代方案

javascript - 如何每 90 秒触发一次 Azure 计时器功能?

javascript - 在 if 语句内部或外部声明变量是更好的做法吗?

javascript - 删除最后一个项目元素JQuery

Javascript onload 和 onunload