перейти к части...
Отображаем товары в корзине
Давайте начнем с отображения товаров в корзине, чтобы мы могли увидеть добавленные товары сразу же после того, как мы сделаем функционал добавления. Все будет очень просто, обычный цикл. Отредактируйте шаблон компонента Cart.vue
вот так:
<template>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="">
Корзина ({{ $store.state.cartCount }})
</a>
<div v-if="$store.state.cart.length > 0" class="navbar-dropdown is-boxed is-right">
<a v-for="item in $store.state.cart"
:key="item.id"
class="navbar-item"
href=""
>
{{ item.title }} x{{ item.quantity }} - ${{ item.totalPrice }}
</a>
<a class="navbar-item" href="">
Итого: ${{ totalPrice }}
</a>
<hr class="navbar-divider">
<a class="navbar-item" href="">
К оплате
</a>
</div>
<div v-else class="navbar-dropdown is-boxed is-right">
<a class="navbar-item" href="">
Корзина пуста
</a>
</div>
</div>
</template>
Опять ничего нового, стандартный код Vue. Конечно же, пока что мы не увидим результатов. Двигаемся дальше.
Добавление товаров в корзину
Чтобы добавить товар в корзину, нам нужно модифицировать состояние cart
в хранилище Vuex. Для модификаций состояний используются мутации
. Мутации это своего рода сеттеры для состояний. Давайте создадим мутацию для добавления товара в корзину в файле store.js
.
let store = {
state: {
cart: [],
cartCount: 0,
},
mutations: {
addToCart(state, item) {
console.log(item.title);
}
}
};
Мутации всегда принимают объект state
на входе в качестве первого аргумента. Пока что мы просто выведем название переданного товар товара в консоль браузера. Вернемся в компонент ProductsList.vue
. Найдите элемент <td>
с текстом Добавить в корзину
в шаблоне и замените его на кнопку:
<td>
<button class="button is-success"
@click="addToCart(item)">Add to Cart</button>
</td>
Дальше добавьте метод addToCart
в раздел script
. В методе мы вызовем нашу единственную Vuex мутацию, передав в качестве параметра объект товара.
methods: {
addToCart(item) {
this.$store.commit('addToCart', item);
}
}
Обновите страницу и вы должны увидеть заголовок товара, добавляемого в корзину, в консоли браузера каждый раз, когда вы нажимаете на кнопку "Добавить в корзину". Вернемся к мутации addToCart
в файле store.js
. Внутри нам нужно всего-то добавить товар в массив cart
и увеличить счетчик cartCount
на 1.
mutations: {
addToCart(state, item) {
state.cart.push(item);
state.cartCount++;
}
}
Этого кода достаточно для того, чтобы увидеть, как товары добавляются в корзину и увеличивается их счетчик. Круто, правда? Хотя, сейчас все будет выглядеть не так, как должно. Кроме того, в консоли браузера будут ошибки. Все потому, что мы обращаемся к свойства товара quantity
и totalPrice
при отображении корзины, однако у наших товаров таких свойств изначально нет. Мы добавим эти свойства на ходу, для этого отредактируйте мутацию вот так:
addToCart(state, item) {
let found = state.cart.find(product => product.id == item.id);
if (found) {
found.quantity ++;
found.totalPrice = found.quantity * found.price;
} else {
state.cart.push(item);
Vue.set(item, 'quantity', 1);
Vue.set(item, 'totalPrice', item.price);
}
state.cartCount++;
}
Здесь мы проверяем, был ли товар уже добавлен в корзину ранее. Если да - мы просто увеличиваем счетчик товара на 1 и заново рассчитываем суммарную цену для данного наименования. Если нет - мы добавляем товар в массив cart
и затем вручную добавляем недостающие свойства товару с помощью Vue.set()
- только так эти свойства станут реактивными.
Попробуйте подобавлять товары в корзину снова. Попробуйте добавить один и тот же товар несколько раз. Вы увидите, как растет количество и суммарная цена каждого наименования товара. Остается только рассчитать полную стоимость всей корзины. Для этого мы просто добавим вычисляемое свойство в Cart.vue
.
computed: {
totalPrice() {
let total = 0;
for (let item of this.$store.state.cart) {
total += item.totalPrice;
}
return total.toFixed(2);
}
}
Удаляем товары из корзины
Теперь давайте займемся удалением товаров. Откройте Cart.vue
. Давайте добавим кнопку удаления возле каждого товара в шаблоне.
<a v-for="item in $store.state.cart"
:key="item.id"
class="navbar-item"
href=""
>
<span class="removeBtn"
title="Удалить из корзины"
@click.prevent="removeFromCart(item)">X</span>
{{ item.title }} x{{ item.quantity }} - ${{ item.totalPrice }}
</a>
Добавим немного стилей для кнопки в конец файла компонента.
<style>
.removeBtn {
margin-right: 1rem;
color: red;
}
</style>
Наконец добавим метод removeFromCart
, который будет вызывать мутацию Vuex.
methods: {
removeFromCart(item) {
this.$store.commit('removeFromCart', item);
}
}
Создадим недостающую мутацию в файле store.js
.
removeFromCart(state, item) {
let index = state.cart.indexOf(item);
if (index > -1) {
let product = state.cart[index];
state.cartCount -= product.quantity;
state.cart.splice(index, 1);
}
}
Все очень просто. Если товар найден в корзине, то мы вычитаем количество товара в корзине из общего счетчика товаров, после чего удаляем товар из массива cart
.
Сохраняем корзину
Единственная оставшаяся проблема - наша корзина очищается при каждом обновлении страницы или переходе на другую страницу сайта. Мы можем сохранять нашу корзину в локальном хранилище HTML5. Добавьте новую мутацию в файл store.js
.
saveCart(state) {
window.localStorage.setItem('cart', JSON.stringify(state.cart));
window.localStorage.setItem('cartCount', state.cartCount);
}
Нам нужно вызвать эту мутацию в конце мутаций addToCart
и removeFromCart
следующим образом:
this.commit('saveCart');
И наконец, нам нужно прочитать данные из локального хранилища при загрузке страницы. Сначала добавьте следующие две строчки в самое начала файла store.js
:
let cart = window.localStorage.getItem('cart');
let cartCount = window.localStorage.getItem('cartCount');
Затем замените инициализацию состояний хранилища Vuex на следующее:
state: {
cart: cart ? JSON.parse(cart) : [],
cartCount: cartCount ? parseInt(cartCount) : 0,
},
Все! Теперь данные из корзины не будут теряться при перезагрузке страницы и должны сохраняться даже если вы закроете браузер.
Страница оплаты
Вам остается только отправить данные из корзины на сервер (backend) с предполагаемоей страницы оплаты/совершения покупки. Это можно легко сделать с помощью axios
, например вот так:
let data = {
cart: JSON.stringify(this.$store.state.cart)
}
axios.post('/ваш-маршрут', data);
После этого вы можете прочитать данные на стороне Laravel (PHP) следующим образом:
$cart = json_decode(request('cart'));
Однако, не принимайте эти данные как есть, ибо все, что приходит из frontend'а должно всегда дополнительно проверяться в backend'е. Вы можете взять из массива $cart
только id и кол-во товаров, а непосредственно информацию о товарах вытащить из БД используя эти id. Таким образом вы будете уверены, что важные данные никто не подменил.
Все материалы на сайте voerro абсолютно бесплатны и написаны автором в свободное от основной работы время. Если уроки сайта оказались для вас полезными, пожалуйста, помогите проекту. Спасибо!