【问题标题】:How to make vuex state update UI when it's updated?如何在更新时制作 vuex 状态更新 UI?
【发布时间】:2020-07-02 11:04:04
【问题描述】:

我正在使用 Vuejs 和 Vuex 构建购物车页面。购物车中的每件商品都应有一个数量计数器,以增加或减少为此特定商品订购的件数。 当我从主产品页面将产品添加到购物车时,然后访问购物车页面。我点击柜台,产品数量发生了变化,但 UI 没有显示这种变化。它仅在我重新加载页面后显示更改,之后它只能显示对这个特定计数器的任何新更改,并且我必须在添加每个产品后重新加载才能使其计数器显示 UI 更改。

这是购物车 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,但没有运气。 谁能找出我做错了什么?

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-component vuex


    【解决方案1】:

    请仔细阅读 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')
        }
      }
    })
    
    
    

    【讨论】:

    • 谢谢,我现在理解流程更好了,我很感激
    【解决方案2】:

    Vue.js docs:

    默认情况下,计算属性是 getter-only

    您尝试更改没有set method 的计算属性的方式。 可能发生的情况是,仅更改对象属性而不创建新属性可能不会触发更新 UI 的反应。

    我实际上建议采用另一种方法并将逻辑移动到存储的变异方法,仅传递您需要增加/减少的产品的 id。并且还使用了在更新后返回一个全新对象的方法(比如我用来更改cartProductsmap()方法。

    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>
    

    【讨论】:

    • 成功了,非常感谢!我在理解 Vuex 流程时遇到了一些问题,但现在清楚多了。
    猜你喜欢
    • 2023-03-16
    • 2020-11-23
    • 1970-01-01
    • 2019-03-20
    • 2021-06-19
    • 2017-05-20
    • 2023-03-21
    • 1970-01-01
    • 2018-05-13
    相关资源
    最近更新 更多