Урок 10 :: Communicating Events :: События связи
Вот, что мы с Вами сделаем на этом уроке.
Пройдем по этой ссылке:
Communicating Events ➳
... Все внимательно послушаем, посмотрим, прочитаем.
Затем сделаем конспект (мой см ниже).
Конспект
События связи (Communicating Events)В этом уроке мы рассмотрим концепцию событий связи, которые происходят внутри наших компонентов.
Чтобы начать этот урок, вы можете либо получить программой git коммандой checkout исходный код в ветке
L10-start
репозитория, либо перейти в CodePen, чтобы взять файлы там.
Примечание переводчика
Чтобы перейти на ветку с файлами начала урока 10 выполните команду:
git checkout L10-start
Наша Цель
Дать нашему компоненту возможность сообщить своему родителю о событии, произошедшем внутри него. Другими словами, обеспечить возможность передавать информацию о событии от дочки к родителю.
Излучение (эмитирование) события (Emitting the event)
Когда мы переработали программы на нашем последнем уроке, переместив код, связанный с продуктом, в новый компонент отображения продукта (
product-display
), мы отключили возможность нажимать кнопку "Добавить в корзину" ("Add to Cart"
) и увеличивать значение количества товара в корзине (cart
). Это связано с тем, что корзина (cart
) живет за пределами компонента отображения продукта, внутри корневого приложения Vue в main.js.
Нам нужно дать компоненту отображения продукта (
product-display
) возможность объявить о том, что его кнопка нажата. Как нам добиться того, чтобы это произошло?
Мы уже знаем, что пропсы (
props
) - это способ передачи данных в дочерний компонент, но как насчет того, когда внутри этого компонента что-то происходит, например, нажатие кнопки? Как мы можем сообщить другим частям нашего приложения о том, что это событие произошло?
Ответ состоит в том, чтобы выдать (излучить, эмитировать, emit) это событие, сообщив родителю, что оно произошло. Давайте добавим эту возможность в наш компонент отображения продукта (
product-display
), изменив метод addToCart()
.
📄 components/ProductDisplay.js
methods: { addToCart() { this.$emit('add-to-cart') } ... }
Мы напишем
this.$emit()
и создадим событие под названием 'add-to-cart'
("добавить в корзину"). Поэтому, когда нажимается кнопка, мы эмитируем, или испускаем, или выплескиваем (bubbling up) это событие. Мы можем прослушивать это событие из родительской области, где мы используем отображение продукта (product-display
), добавив прослушиватель: @add-to-cart
.
📄 index.html
<product-display :premium="premium" @add-to-cart="updateCart"></product-display>
Когда это событие “услышит” родитель, то этот родитель вызовет новый метод с именем
updateCart
, который мы добавим в main.js (см код ниже картинки).
📄 main.js
const app = Vue.createApp({ data() { return { cart: [], ... } }, methods: { updateCart() { this.cart += 1 } } })
Если мы проверим эти наработки в браузере, то обнаружим следующее. Теперь мы сможем нажать кнопку "Добавить в корзину" ("Add To Cart"), которая позволит родителю узнать, что произошло событие "Добавить в корзину" (
add-to-cart
), и это событие запускает метод updateCart()
.
Добавление идентификатора товара id в корзину
Чтобы сделать наше приложение более реалистичным, наша корзина (
cart
) не должна быть просто числом. Это должен быть массив, содержащий идентификаторы продуктов, которые в него добавляются. Так что давайте проведем небольшой рефакторинг.
📄 main.js
const app = Vue.createApp({ data() { return { cart: [], ... } }, methods: { updateCart(id) { this.cart.push(id) } } })
Теперь корзина (
cart
) представляет собой массив, и updateCart(id)
помещает в нее идентификатор продукта (id
). Нам просто нужно добавить полезную нагрузку в наше событие добавления в корзину (add-to-cart
), чтобы у updateCart
был доступ к этому идентификатору (id
).
📄 components/ProductDisplay.js
methods: { addToCart() { this.$emit('add-to-cart', this.variants[this.selectedVariant].id) } ... }
Здесь мы добавили второй параметр и захватили идентификатор продукта (
id
) так же, как мы захватили изображение (image
) и количество (quantity
) раньше:
📄 components/ProductDisplay.js
computed: { image() { return this.variants[this.selectedVariant].image }, inStock() { return this.variants[this.selectedVariant].quantity } }
Теперь в браузере вы можете видеть, что мы добавляем идентификаторы товаров в корзину, которая теперь представляет собой массив.
Но нам не нужно на самом деле отображать эти идентификаторы. Мы просто хотим показать, сколько товаров находится в корзине. К счастью есть быстрое и простое решение.
📄 index.html
<div id="app"> ... <div class="cart">Cart({{ cart.length }})</div> ... </div>
Добавив
cart.length
, мы теперь будем отображать только количество товаров в корзине (cart
).
Задача кодирования
Мы подошли к концу этого урока, теперь будем решать новые задачи кодирования.
Вот, что надо сделать.
Добавьте новую кнопку к
product-display
, при клике на которую удалялся 1 товар из корзины (cart
).
Вы можете найти код решения, загрузив L10-end ветвь репозитория или просмотрев решение в Codepen.
Чтобы перейти на ветку с файлами окончания урока 10 выполните команду:
git checkout L10-end
Код файла index.html данного урока
<div id="app"> <div class="nav-bar"></div> <div class="cart">Cart({{ cart.length }})</div> <product-display :premium="premium" @add-to-cart="updateCart" @remove-from-cart="removeById"> <!-- solution --> </product-display> </div> <!-- Import App --> <script src="./main.js"></script> <!-- Import Components --> <script src="./components/ProductDisplay.js"></script> <!-- Mount App --> <script> const mountedApp = app.mount('#app') </script
Код файла main.js данного урока
См здесь: Код файла main.js данного урокаКод файла ProductDisplay.js данного урока
См здесь: Код файла ProductDisplay.js данного урокаРезультат выполнения данного урока
Cart({{ cart.length }})
Примечание переводчика
1. Я слегка меняю контент оригинальных файлов курса для тренировки, проверки русификации и т.д.
2. Код для
HTML
я размещаю в этом файле между тегами body
.
3. Обратите внимание, чтобы в консоле браузера не было ошибок.
Теперь Нажмите здесь для перехода к следующему уроку ➳
... или ...