Vue.js для начинающих, урок 1: экземпляр Vue
Vue.js для начинающих, урок 2: привязка атрибутов
Vue.js для начинающих, урок 3: условный рендеринг
Vue.js для начинающих, урок 4: рендеринг списков
Цель урока
Первая цель урока заключается в том, чтобы в карточке товара появилась бы кнопка, нажатия на которую увеличивают количество товара в корзине.
Вторая цель заключается в том, чтобы при наведении мыши на названия цветов вариантов товара менялось бы изображение товара.
Начальный вариант кода
В файле проекта
index.html
будет присутствовать
следующий код:
<div id="app"><div class="product"><div class="product-image"><img :src="image" /></div><div class="product-info"><h1>{{ product }}</h1><p v-if="inStock">In stock</p><p v-else>Out of Stock</p><ul><li v-for="detail in details">{{ detail }}</li></ul><div v-for="variant in variants" :key="variant.variantId"><p>{{ variant.variantColor }}</p></div></div></div></div>
Вот содержимое
main.js
:
var app = new Vue({el: '#app',data: {product: "Socks",image: "./assets/vmSocks-green.jpg",inStock: true,details: ['80% cotton', '20% polyester', 'Gender-neutral'],variants: [{variantId: 2234,variantColor: "green"},{variantId: 2235,variantColor: "blue"}]}})
Задача
Нам нужна кнопка, которой будет назначен прослушиватель события, реагирующий на щелчок по ней. По щелчку должен запускаться метод, который и выполняет увеличение количества товара в корзине.
Решение
Для начала добавим, в
main.js
, в объект
data
, новое свойство, которое будет символизировать
количество товара в корзине:
cart: 0
Теперь, в
index.html
, добавим элемент
<div>
, описывающий корзину. В этом элементе
будет использован тег <p>
, с помощью которого на
страницу будет выводиться число, хранящееся в свойстве
cart
:
<div class="cart"><p>Cart({{ cart }})</p></div>
Ещё мы создадим в коде
index.html
кнопку, которая
позволяет добавлять товар в корзину:
<button v-on:click="cart += 1">Add to cart</button>
Здесь обратите внимание на то, что для инкрементирования значения, хранящегося в
cart
, мы используем директиву
v-on
.Страница с корзиной и с кнопкой для добавления товара в корзину
Если теперь нажать на кнопку количество товара в корзине увеличится на 1.
Как всё это работает?
Давайте разберёмся в представленной здесь конструкции. Использование директивы
v-on
сообщает Vue о том, что
мы хотим прослушивать события, происходящие с кнопкой. Потом идёт
двоеточие, после которого указывается то, какое конкретно событие
нас интересует. В данном случае это событие click
. В
кавычках записано выражение, которое добавляет 1 к значению,
хранящемуся в cart
. Это происходит при каждом щелчке
по кнопке.Это простой, но не вполне реалистичный пример. Вместо того, чтобы указывать в кавычках выражение
cart += 1
, давайте
сделаем так, чтобы щелчок по кнопке вызывал бы метод, который будет
увеличивать значение, хранящееся в cart
. Вот как это
выглядит:
<button v-on:click="addToCart">Add to cart</button>
Как видите, здесь
addToCart
это имя метода, который
будет вызван при возникновении события click
. Но сам
метод мы пока не объявили, поэтому давайте сделаем это прямо
сейчас, оснастив им наш экземпляр Vue.Тут используется механизм, очень похожий на тот, который мы уже применяем для хранения данных. А именно, речь идёт о том, что у объекта с опциями, используемого при создании экземпляра Vue, может быть необязательное свойство, носящее имя
methods
, в
котором содержится объект с методами. В нашем случае это будет
всего один метод addToCart
:
methods: {addToCart() {this.cart += 1}}
Теперь, когда мы щёлкаем по кнопке, вызывается метод
addToCart
, который и увеличивает значение
cart
, выводящееся в теге <p>
.Продолжим разбор того, что здесь происходит.
Кнопка прослушивает события
click
благодаря директиве
v-on
, которая вызывает метод addToCart
.
Этот метод находится в свойстве methods
экземпляра
Vue. В теле функции содержится инструкция, добавляющая 1 к значению
this.cart
. Так как this
хранит ссылку на
то место, где хранятся данные экземпляра Vue, в котором мы
находимся, функция добавляет 1 к значению cart
. А
this.cart
это то же самое, что и свойство
cart
, объявленное в свойстве data
объекта
с опциями.Если бы мы просто написали бы в теле функции что-то вроде
cart += 1
, то мы столкнулись бы с сообщением об ошибке
cart is not defined
. Именно поэтому мы используем
конструкцию this.cart
и обращаемся к cart
из экземпляра Vue, используя this
.Возможно, вы сейчас задаётесь вопросом о том, что сейчас мы просто увеличиваем количество товаров в корзине, но самого товара в корзину не добавляем. Может, мы что-то делаем не так? Это правильный вопрос. Мы реализуем соответствующий функционал позже, в одном из следующих уроков.
Итак, теперь, когда мы изучили основы обработки событий во Vue, взглянем на более сложный пример.
Для начала давайте расширим объекты массива
variants
из объекта data
, добавив туда свойство
variantImage
, хранящее путь к изображению нужного
варианта товара. Приведём соответствующий раздел файла
main.js
к такому виду:
variants: [{variantId: 2234,variantColor: "green",variantImage: "./assets/vmSocks-green.jpg"},{variantId: 2235,variantColor: "blue",variantImage: "./assets/vmSocks-blue.jpg"}],
Теперь каждому варианту товара, зелёным и синим носкам, назначено собственное изображение.
Задача
Нужно, чтобы, по наведению мыши на название цвета варианта носков, в поле, где выводится изображение товара, вывелось бы изображение
variantImage
для соответствующего цвета.Решение
Тут нам снова пригодится директива
v-on
. Но в этот раз
мы воспользуемся сокращённым вариантом её записи, который выглядит
как @
. А прослушивать будем событие
mouseover
.Вот соответствующий код в
index.html
:
<div v-for="variant in variants" :key="variant.variantId"><p @mouseover="updateProduct(variant.variantImage)">{{ variant.variantColor }}</p></div>
Обратите внимание на то, что мы передаём методу
updateProduct
, в виде аргумента,
variant.variantImage
.Создадим этот метод в
main.js
:
updateProduct(variantImage) {this.image = variantImage}
Этот метод очень похож на тот, который мы недавно создавали для увеличения значения
cart
.Но тут мы обновляем значение, хранящееся в
image
. А
именно, в image
записывается то, что хранится в
variantImage
того варианта товара, на который наведён
указатель мыши. Соответствующее значение передаётся функции
updateProduct
из самого обработчика события,
находящегося в index.html
:
<p @mouseover="updateProduct(variant.variantImage)">
Другими словами, теперь метод
updateProduct
готов к
вызову с параметром variantImage
.Когда вызывается этот метод,
variant.variantImage
передаётся ему в виде variantImage
и используется для
обновления значения, хранящегося в this.image
. Мы, по
аналогии с ранее рассмотренной конструкцией this.cart
,
можем сказать, что this.image
это то же самое, что
image
. В результате значение, хранящееся в
image
, теперь динамически обновляется в соответствии с
данными варианта товара, на который наведён указатель мыши.Синтаксис ES6
Здесь мы, создавая методы, пользовались такими конструкциями:
updateProduct(variantImage) {this.image = variantImage}
Это сокращённый вариант описания методов, который появился в ES6. Более старый вариант записи подобных конструкций выглядит так:
updateProduct: function(variantImage) {this.image = variantImage}
Практикум
Создайте кнопку и соответствующий метод, которые позволят уменьшать значение, хранящееся в
cart
.Вот заготовка, которую вы можете использовать для решения этой задачи.
Вот решение задачи.
Итоги
Подведём итоги сегодняшнего занятия:
- Для организации реакции элемента на события используется
директива
v-on
. - Сокращённый вариант директивы
v-on
выглядит как@
. - При использовании
v-on
можно указать тип прослушиваемого события:- click
- mouseover
- любое событие DOM
- Директива
v-on
может вызывать методы. - Метод, вызываемый с помощью
v-on
, может принимать аргументы. - Ключевое слово
this
содержит ссылку на то место, где хранятся данные текущего экземпляра Vue. Его использование позволяет работать с данными экземпляра, а так же с методами, объявленными в экземпляре.
Получилось ли у вас домашнее задание к этому уроку?
Vue.js для начинающих, урок 1: экземпляр Vue
Vue.js для начинающих, урок 2: привязка атрибутов
Vue.js для начинающих, урок 3: условный рендеринг
Vue.js для начинающих, урок 4: рендеринг списков