перейти к части...
Для начала давайте создадим новый проект на Laravel.
laravel new cart
cd cart
Откройте проект в вашей любимой IDE, затем откройте файл package.json
. Давайте удалим некоторые ненужные нам зависимости и добавим новые. Вот как должен выглядеть блок devDependencies
после изменений:
"devDependencies": {
"axios": "^0.18",
"bulma": "^0.7.1",
"cross-env": "^5.1",
"laravel-mix": "^2.0",
"vue": "^2.5.7",
"vuex": "^3.0.1"
}
Сохраните файл и выполните команду npm install
, чтобы установить все зависимости. Обратите внимание, что я заменил bootstrap
на bulma
- это всего лишь личное предпочтение, CSS фреймворк не играет значения в данном уроке. Теперь давайте внесем соответствующие изменения в файлы ресурсов. Начнем с sass. Зайдите в папку resources/assets/sass
и удалите файл _variables.scss
. Затем откройте app.scss
и замените его содержимое на это:
@import '~bulma/bulma';
Дальше папка resources/assets/js
. Отредактируйте bootstrap.js
следующим образом:
import axios from 'axios';
import Vue from 'vue';
window.axios = axios;
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
window.Vue = Vue;
И затем файл app.js
:
require('./bootstrap');
Vue.component('example-component', require('./components/ExampleComponent.vue'));
const app = new Vue({
el: '#app'
});
Как вы заметили, мы оставили только Vue
и axios
в этих файлах, так как мы удалили все остальные зависимости в package.json
.
Наконец давайте отредактируем view resources/views/welcome.blade.php
. Это будет нашим основным и единственным шаблоном в этом уроке. Внутри шаблона присутствует стандартная разметка Bulma.
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Voerro Tutorial - Shopping Cart w/ Vue.js 2 & Vuex</title>
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
</head>
<body>
<div id="app">
<nav class="navbar is-primary">
<div class="navbar-brand">
<a class="navbar-item" href="/">
Voerro Shopping Cart Tutorial
</a>
<div class="navbar-burger burger">
<span></span>
<span></span>
<span></span>
</div>
</div>
<div id="navbarExampleTransparentExample" class="navbar-menu">
<div class="navbar-end">
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="">
Корзина (0)
</a>
<div class="navbar-dropdown is-boxed is-right">
<a class="navbar-item" href="">
Корзина пуста
</a>
<hr class="navbar-divider">
<a class="navbar-item" href="">
К оплате
</a>
</div>
</div>
</div>
</div>
</nav>
<div class="section content">
<h1>Our Products</h1>
</div>
</div>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
Список товаров
Нам нужно отобразить список товаров нашего магазина. Мы могли бы использовать Vue в связке с Laravel для этих целей, но давайте сделаем все проще. К тому же, я обещал, что мы будем работать только (или по большей части) с frontend технологиями.
Начнем с того, что переименуем файл resources/assets/js/components/ExampleComponent.vue
в ProductsList.vue
. Затем откройте файл resources/assets/js/app.js
и замените Vue.component('example-component', require('./components/ExampleComponent.vue'));
на Vue.component('products-list', require('./components/ProductsList.vue'));
. Вернитесь в файл view и вставьте следующий код под заголовком h1
:
<products-list></products-list>
Запустите наблюдатель npm выполнив команду npm run watch
или просто скомпилируйте ресурсы единоразово выполнив npm run dev
. Перезагрузите страницу браузера и вы должны увидеть стандартный компонент-пример Vue под заголовком. Отлично, теперь мы можем начать работать над ProductsList.vue
. Сначала отредактируйте раздел <script>
вот так:
<script>
export default {
data() {
return {
items: [
{
id: 1,
title: 'Children of Bodom - Hatebreeder',
price: 9.99
},
{
id: 2,
title: 'Emperor - Anthems to the Welkin at Dusk',
price: 6.66
},
{
id: 3,
title: 'Epica - The Quantum Enigma',
price: 15.99
},
{
id: 4,
title: 'Chthonic - Takasago Army',
price: 14.00
},
{
id: 5,
title: 'Silencer - Death - Pierce Me',
price: 1.20
},
{
id: 6,
title: 'My Dying Bride - 34.788%... Complete',
price: 10.00
},
{
id: 7,
title: 'Shape of Despair - Shades of',
price: 7.80
},
{
id: 8,
title: 'Ne Obliviscaris - Portal of I',
price: 11.30
},
{
id: 9,
title: 'Protest the Hero - Fortress',
price: 5.55
},
{
id: 10,
title: 'Dark Lunacy - Devoid',
price: 6.00
},
]
};
}
}
</script>
Мы просто создали статичный список продуктов, которые в данный момент в наличии в нашем магазине. В реальном проекте вы бы сделали AJAX запрос на сервер, чтобы получить данные из БД, но для простоты примера мы не будем этого делать. Предположительно, наш магазин продает музыкальные компакт-диски. Дальше отредактируем блок <template>
, чтобы он выводил список товаров.
<template>
<table>
<thead>
<th>Название</th>
<th>Цена</th>
<th></th>
</thead>
<tbody>
<tr v-for="item in items" :key="item.id">
<td v-text="item.title"></td>
<td>${{ item.price.toFixed(2) }}</td>
<td>Добавить в корзину</td>
</tr>
</tbody>
</table>
</template>
Весь код выше это простейший код Vue, поэтому у вас не должно возникнуть по нему вопросов. Перекомпилируйте ресурсы, обновите страницу браузера и вы должны увидеть список товаров в виде обычной таблицы.
Подключаем Vuex
Как вы уже поняли, на данный момент у нас есть отдельный Vue компонент для отображения списка продуктов. Также на странице у нас есть выпадающий список корзины в верхнем меню, который тоже будет отдельным Vue компонентом. Когда мы добавляем товар в корзину из компонента со списком товаров, это должно отобразиться в компоненте корзины. Другими словами, наши компоненты должны как-то общаться друг с другом.
Вы, наверное, слышали, что коммуникацию между компонентами можно сделать с помощью глобальных событий или глобальных переменных. Однако в этот раз мы будем использовать Vuex, который "служит централизованным хранилищем данных для всех компонентов приложения". В нашем уроке мы будем использовать хранилище Vuex для хранения товаров корзины. У каждого компонента сайта будет доступ к этом хранилищу с возможностью редактирования данных. Данные в хранилище Vuex реактивны по-умолчанию.
Для начала давайте импортируем Vuex в файле bootstrap.js
:
import Vuex from 'vuex';
...
window.Vuex = Vuex;
Vue.use(Vuex);
Затем сделаем следующие изменения в файле app.js
:
import store from './store.js';
new Vue({
el: '#app',
store: new Vuex.Store(store)
});
Наше Vuex хранилище будет находиться в отдельном файле, чтобы не загромождать app.js
. Создайте файл resources/assets/js/store.js
со следующим содержимым:
let store = {
};
export default store;
Как вы видите, хранилище Vuex это простой объект с набором специальных свойств. Давайте начнем со свойства state
(состояния). state
это что-то вроде аналога свойства data
в компонентах Vue. В нашем state
мы будем хранить массив товаров, добавленных в корзину, а так же отдельно счетчик количества этих товаров.
let store = {
state: {
cart: [],
cartCount: 10,
},
};
Я временно установил значение счетчика на 10, чтобы мы могли попробовать прочитать и отобразить это значение в шапке сайта. Давайте создадим новый компонент resources/assets/js/components/Cart.vue
. Зарегистрируйте компонет в app.js
:
Vue.component('cart-dropdown', require('./components/Cart.vue'));
Мы вырежем кусок HTML из view и вставим его в новый компонент. Итак, вот наш Cart.vue
:
<template>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link" href="">
Корзина (0)
</a>
<div class="navbar-dropdown is-boxed is-right">
<a class="navbar-item" href="">
Корзина пуста
</a>
<hr class="navbar-divider">
<a class="navbar-item" href="">
К оплате
</a>
</div>
</div>
</template>
<script>
export default {
}
</script>
Откройте welcome.blade.php
, найдите кусок кода, который мы вставили в компонент, замените его на <cart-dropdown></cart-dropdown>
. После перезагрузки страницы визуально ничего не должно поменяться. В нашем компоненте число товаров в корзине статично и всегда равно "0". Давайте выведем реальное значение счетчика товаров из хранилища Vuex вместо этого нуля. Отредактируйте соответствующий кусок шаблона компонента следующим образом:
<a class="navbar-link" href="">
Корзина ({{ $store.state.cartCount }})
</a>
Каждый раз, когда мы будем менять значение состояния cartCount
в хранилище, интерфейс пользователя будет автоматически обновляться. Неплохо, неправда ли? Теперь давайте вернемся в store.js
и зададим счетчику значение 0, каким оно и должно быть. Пока что все. Мы займемся разработкой непосредственно корзины в следующей части урока.
Все материалы на сайте voerro абсолютно бесплатны и написаны автором в свободное от основной работы время. Если уроки сайта оказались для вас полезными, пожалуйста, помогите проекту. Спасибо!