Как сделать так, чтобы Vuex State обновлял интерфейс после его обновления? - PullRequest
0 голосов
/ 21 марта 2020

Я создаю страницу корзины покупок, используя Vuejs и Vuex. Каждый товар в корзине должен иметь счетчик количества, чтобы увеличить или уменьшить количество товаров, заказанных для данного товара c. Когда я добавляю товары в корзину с главной страницы товаров, тогда посещаю страницу корзины. Я нажимаю на счетчик, и количество продукта изменяется, но пользовательский интерфейс не показывает это изменение. Изменения отображаются только после перезагрузки страницы, и после этого могут отображаться любые новые изменения только для этого указанного счетчика c, и после добавления каждого продукта мне приходится перезагружать только для того, чтобы его счетчик отображал изменения пользовательского интерфейса.

Это упрощенный компонент корзины Vue:

 <template >
    <tbody>
        <tr v-for="product in cartProducts" :key="product.name">
            <td class="quantity">
                <i class="fa fa-minus" @click="decreaseQuantity(product)"></i>
                <p>{{product.quantity}}</p>
                <i class="fa fa-plus" @click="increaseQuantity(product)"></i>
            </td>
        </tr>
    </tbody>
</template>

<script>
export default {
    computed: {
        cartProducts() {
            return this.$store.state.cartProducts;
        },
    },
    methods: {
        increaseQuantity(drug) {
            const existedDrug = this.cartProducts.find(d => d.id === drug.id);
            existedDrug.quantity += 1;
            this.$store.dispatch("setUserDataCart", this.cartProducts);
            console.log(this.$store.state.cartProducts);
        },
        decreaseQuantity(drug) {
            const existedDrug = this.cartProducts.find(d => d.id === drug.id);
            existedDrug.quantity -= 1;
            this.$store.dispatch("setUserDataCart", this.cartProducts);
            console.log(this.$store.state.cartProducts);
        },
    },
};
</script>

И это мое хранилище vuex:

import Vue from "vue";
import Vuex from "vuex";
import VuexPersist from "vuex-persist";

Vue.use(Vuex);
const vuexPersist = new VuexPersist({
  key: "my-app",
  storage: window.localStorage
});

const store = new Vuex.Store({
  state: {
    cartProducts: []
  },
  mutations: {
    SET_USER_CART(state, data) {
      state.cartProducts = data;
    }
  },
  actions: {
    setUserDataCart({ commit }, data) {
      commit("SET_USER_CART", data);
    }
  },
  plugins: [vuexPersist.plugin]
});

export default store;

Я пробовал несколько подходов, таких как mapState или использование состояния. как getter но не повезло. Кто-нибудь может определить, что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 22 марта 2020

В Vue. js документы :

По умолчанию вычисляемые свойства доступны только для получателя

То, как вы это сделали пытаемся изменить вычисляемое свойство без метода set . Может случиться так, что изменение только свойства объекта и не создание нового может не вызвать реакцию на обновление пользовательского интерфейса.

На самом деле я бы порекомендовал использовать другой подход и переместить логи c в метод мутации магазина, передавая только идентификатор продукта, который нужно увеличить / уменьшить. А также используйте метод, который возвращает новый объект после обновления (например, метод map(), который я использую для изменения cartProducts.

store. js:

import Vue from "vue";
import Vuex from "vuex";
import VuexPersist from "vuex-persist";

Vue.use(Vuex);
const vuexPersist = new VuexPersist({
  key: "my-app",
  storage: window.localStorage
});

export default new Vuex.Store({
  state: {
    cartProducts: [
      {
        id: 1,
        name: "Drug 1",
        quantity: 1
      },
      {
        id: 2,
        name: "Drug 2",
        quantity: 1
      }
    ]
  },
  mutations: {
    INCREMENT(state, productId) {
      state.cartProducts = state.cartProducts.map(product => {
        if (product.id === productId) {
          product.quantity += 1;
        }
        return product;
      });
    },
    DECREMENT(state, productId) {
      state.cartProducts = state.cartProducts.map(product => {
        if (product.id === productId) {
          product.quantity -= 1;
        }
        return product;
      });
    }
  },
  actions: {
    incrementQuantity({ commit }, productId) {
      commit("INCREMENT", productId);
    },
    decrementQuantity({ commit }, productId) {
      commit("DECREMENT", productId);
    }
  },
  plugins: [vuexPersist.plugin]
});

cart . js

<template>
  <table>
    <tbody>
      <tr v-for="product in cartProducts" :key="product.name">
        <td class="quantity">
          <button @click="decreaseQuantity(product)">decrease</button>
          <p>{{ product.quantity || 0 }}</p>
          <button @click="increaseQuantity(product)">increase</button>
        </td>
      </tr>
    </tbody>
  </table>
</template>

<script>
export default {
  computed: {
    cartProducts() {
      return this.$store.state.cartProducts;
    }
  },
  methods: {
    increaseQuantity(drug) {
      this.$store.dispatch("incrementQuantity", drug.id);
    },
    decreaseQuantity(drug) {
      this.$store.dispatch("decrementQuantity", drug.id);
    }
  }
};
</script>
0 голосов
/ 21 марта 2020

Пожалуйста, внимательно прочитайте документацию vuex. - https://vuex.vuejs.org/guide/ Изменение состояния должно происходить в методах мутации. Вот простой пример из Документов:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})


...