После того, как я полностью сделал корзину, реактивность пропала. При добавлении товара в корзину, счетчик обновляется только после перезагрузки, и товары не сразу пропадают из корзины. Почему так происходит? Может ли несколько циклов
for
так тормозить сайт?
import Vue from "vue";
import Vuex from "vuex";
import Axios from "axios";
let cart = window.localStorage.getItem('cart');
let cartCount = window.localStorage.getItem('cartCount');
Vue.use(Vuex);
export const store = new Vuex.Store({
state: {
products: null,
cart: cart ? JSON.parse(cart) : {},
cartCount: cartCount ? parseInt(cartCount) : 0,
},
getters: {
PRODUCTS: state => {
return state.products;
}
},
mutations: {
addToCart(state, item) {
if (state.cart == null) {
state.cart = {};
}
let cartItem = state.cart[item.id];
if (state.cart[item.id]) {
cartItem.quantity++
cartItem.totalPrice = cartItem.quantity * cartItem.price;
} else {
state.cart[item.id] = item;
Vue.set(item, 'quantity', 1);
Vue.set(item, 'totalPrice', Number(item.price));
}
state.cartCount;
this.commit('saveCart');
},
removeFromCart(state, item) {
let product = state.cart[item.id];
state.cartCount -= product.quantity;
delete state.cart[item.id];
this.commit('saveCart');
},
setQuantity(state, item) {
let found = state.cart.find(product => product.id == item.id);
found.quantity = item.quantity;
this.commit('saveCart');
},
saveCart(state) {
window.localStorage.setItem('cart', JSON.stringify(state.cart));
window.localStorage.setItem('cartCount', state.cartCount);
},
plusQuantity(state, item) {
state.cart[item.id].quantity++;
state.cartCount ++;
this.commit('saveCart');
},
minusQuantity(state, item) {
state.cart[item.id].quantity--;
if(state.cart[item.id].quantity == 0){
delete state.cart[item.id];
}
state.cartCount --;
this.commit('saveCart');
}
},
actions: {
GET_PRODUCTS: async (context, payload) => {
let {
data
} = await Axios.get('/api/products');
context.commit('SET_PRODUCTS', data);
},
},
})
<template>
<div class="container">
<div class="cart">
<div v-if="cartCount > 0">
<div class="cart-item" v-for="item in $store.state.cart" :key="item.id">
<div class="photo">
<img src="http://via.placeholder.com/640x360" alt="" srcset="" />
</div>
<div class="title">
{{ item.title }}
<div class="title-bottom">
<span>Добавить в избранное</span>
<button class="removeBtn" @click.prevent="removeFromCart(item)">Удалить</button>
</div>
</div>
<div class="price">
{{ item.totalPrice.toFixed(2) }}$<br />
<button @click.prevent="minusQuantity(item)">-1</button>
{{ item.quantity }}
<button @click.prevent="plusQuantity(item)">+1</button>
</div>
</div>
</div>
<div v-else>
Корзина пуста<br />
<a href="/">Перейти к покупкам</a>
</div>
</div>
<div class="order">
<span>В корзине {{ cartCount }} товаров на сумму
{{ totalPrice }}</span>
<button>Перейти к оплате</button>
</div>
</div>
</template>
<script>
export default {
computed: {
totalPrice() {
let total = 0;
for (let id in this.$store.state.cart) {
total += Number(this.$store.state.cart[id].price);
}
return total.toFixed(2);
},
cartCount(){
let cartCount = 0;
for(let id in this.$store.state.cart){
cartCount += this.$store.state.cart[id].quantity;
}
return cartCount;
}
},
methods: {
removeFromCart(item) {
this.$store.commit("removeFromCart", item);
},
setQuantity(item) {
this.$store.commit("setQuantity", item);
},
plusQuantity(item) {
this.$store.commit("plusQuantity", item);
},
minusQuantity(item) {
this.$store.commit("minusQuantity", item);
},
},
};
<template>
<div class="container">
<spin v-if="loading"></spin>
<div v-else class="product-list">
<product v-for="product in products" :key="product.id" v-bind="product" :object="product" />
</div>
</div>
</template>
<script>
import Spin from "../components/spin.vue";
import axios from "axios";
import Product from "../components/Product.vue";
export default {
components: {
Spin,
Product,
},
data: () => ({
loading: true,
products: [],
}),
mounted() {
this.loadProducts();
},
methods: {
loadProducts() {
axios.get("/api/products").then((res) => {
this.products = res.data;
setTimeout(() => {
this.loading = false;
}, 500);
});
},
},
};
</script>
<template>
<div class="product">
<div class="product-photo">
<img src="https://loremflickr.com/210/210" alt="" width="210px" height="210px" />
</div>
<div class="product-content">
<span class="product-title">
<router-link :to="/product/ + id">{{
title
}}</router-link>
</span>
<div class="product-bottom">
<div class="product-price">
{{ price }}
</div>
<div class="product-button">
<button v-on:click="addToCart()">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cart-plus" viewBox="0 0 16 16">
<path d="M9 5.5a.5.5 0 0 0-1 0V7H6.5a.5.5 0 0 0 0 1H8v1.5a.5.5 0 0 0 1 0V8h1.5a.5.5 0 0 0 0-1H9V5.5z" />
<path d="M.5 1a.5.5 0 0 0 0 1h1.11l.401 1.607 1.498 7.985A.5.5 0 0 0 4 12h1a2 2 0 1 0 0 4 2 2 0 0 0 0-4h7a2 2 0 1 0 0 4 2 2 0 0 0 0-4h1a.5.5 0 0 0 .491-.408l1.5-8A.5.5 0 0 0 14.5 3H2.89l-.405-1.621A.5.5 0 0 0 2 1H.5zm3.915 10L3.102 4h10.796l-1.313 7h-8.17zM6 14a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm7 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z" />
</svg>
</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
id: {
type: Number,
default: "NULL",
},
title: {
type: String,
default: "NULL",
},
price: {
type: String,
default: "NULL",
},
object: {
type: Object,
default: 'NULL'
}
},
methods: {
addToCart(){
this.$store.commit('addToCart', this.object);
},
}
}
</script>