Урок 10 :: Communicating Events :: События связи

Вот, что мы с Вами сделаем на этом уроке.
Vue Mastery
Пройдем по этой ссылке:
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) - это способ передачи данных в дочерний компонент, но как насчет того, когда внутри этого компонента что-то происходит, например, нажатие кнопки? Как мы можем сообщить другим частям нашего приложения о том, что это событие произошло?
les10_pic01.jpg
Ответ состоит в том, чтобы выдать (излучить, эмитировать, 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 (см код ниже картинки).
les10_pic02.jpg
📄 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
  }
}

Теперь в браузере вы можете видеть, что мы добавляем идентификаторы товаров в корзину, которая теперь представляет собой массив.
les10_pic03.jpg
Но нам не нужно на самом деле отображать эти идентификаторы. Мы просто хотим показать, сколько товаров находится в корзине. К счастью есть быстрое и простое решение.

📄 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. Обратите внимание, чтобы в консоле браузера не было ошибок.

Теперь Нажмите здесь для перехода к следующему уроку ➳

... или ...


Ссылки по теме.