Není bus jako bus

Komunikace byl vždycky problém. Ve firmách, v Angular 1 i v temných dobách Vue. Na začátku jste mohli komunikovat nejen shora dolů do ostatních komponent, ale i směrem nahoru.

Pamatujete?

$scope.$broadcast('udalostSmeremNahoru', {
  text: 'Nějaký text.'
})

Nahoře je kousek kódu z Angularu a ukázka, jak jste mohli notifikovat z potomka směrem nahoru. Kdesi ve stromu jste pak naslouchali na událost.

$scope.$on('udalostSmeremNahoru', function(event, data) {
  console.log(data) // 'Nějaký text'
})

Zní to pěkně, uvolněně, flexibilně - můžete zasílat události shora dolů, zdola nahoru a kus kódu, který má zrovna zájem, na to naslouchá. Ano, v malé aplikaci místního živnostníka asi v pořádku[1]. V rozsáhlejších aplikacích se ale ukazuje pravé peklo. Za prvé - pokud nepoužijete tradiční funkci "vyhledat", tak například nemáte představu, jestli na danou událost vůbec někdo naslouchá. Zůstává vám tak historický kód, který nikdo nepoužívá. Pokud tedy nemáte takovou tu průběžnou integraci (continuous integration) a v pipelině vás to nebuzeruje mrtvým kódem, tak jste prostě v tahu.

Za druhé, proč byste vlastně chtěli notifikovat oběma směry? Pokud chcete mít z kódu dálnici D1, tak se pak nemůžete divit, že na každém několikátém kilometru dochází k nějaké kolizi.

Metrická soustava v životě vývojáře

"Můžu ti poslat 22 cm kódu na revizi?"

Když nemáte žádnou kontrolu nad tím, kudy a jak se předávají jaká data a přesto nemáte kolem postavenou solidní dokumentaci, jak se na svoji aplikaci pak můžete spolehnout? A jakým způsobem dostat data z komponenty C, která je potomkem komponenty B do komponenty A, která je jejím sousedem. Bylo obtížnější předchozí větu nějak pobrat? Je to podobné jako pochopit, kdo je pro vás teta strýce matky vašeho otce. Lidský mozek se nevyvíjel, aby chápal složité vazby.

Co si myslí Daniel?

Kód, který není přehledný, je mučící IT nástroj nejen pro ostatní, ale po půl roce i pro vás.

Voda teče jedním směrem

Ideálnější se tedy ukazuje nechat data protékat jen jedním směrem. A to shora dolů. Nikudy jinudy. Je pak minimálně jasné, že data, která se objevila v komponentě, vám seslal někdo shůry. Existuje několik možností, jak ve Vue.js data dostat z jedné komponenty do druhé. Můžete je posílat přes props. To se v praxi může ukázat jako props hell, pokud máte hodně proměnných, které chcete předávat. Můžete taky používat inteligentní state management typu Vuex. To je fajn řešení ve větších projektech. Na těch ostatních, tedy na většině, je to kladivo na komára.

Článek nyní chytře ústí v řešení. Pojedeme busem.

Bus není jen dopravní prostředek

Bus ve Vue.js je vlastně jen to, co už znáte:

// bus.js
new Vue()

Tedy vytvoření nové instance Vue. A hned máte hotový event bus. Takže kromě již existující instance Vue, pod kterou šlape aplikace, máte jednu novou instanci, která zprostředkuje náš bus.

A jakým způsobem tedy s tímto busem pracovat? Bus je jediné místo, které přijímá a dále distribuuje události. Busů můžete mít i více, pokud se v tom začnete ztrácet, třeba UserBus.js nebo CartBus.js

Praktické využítí - košík

V našem příkladu máme komponentu, která zobrazuje boxík s informacemi o produktu a tlačítkem s možností přidat zboží do košíku.

<!-- product-box.html  -->
<button @click="addToCart(12345)">Přidat do košíku</button>

Při stisknutí tlačítka se zavolá metoda addToCart(), která pak emituje událost do našeho event busu.

// product-box.js
import CartBus from './CartBus'

export default {
  methods: {
    addToCart(productId) {
      CartBus.$emit(`cart.add`, productId)
    }
  }
}

Na druhé straně pak máme komponentu košíku, která naslouchá prostřednictvím úplně stejného event busu.

// cart-bus.js
import CartBus from './CartBus'

export default {
  data() {
    return {
      productId: 0
    }
  },
  created() {
    CartBus.$on(`cart.add`, productId => {
      this.productId = productId
    })
  }
}

Ve výsledku tu pouze přiřadíme proměnné productId konkrétní ID produktu, které touží zákazník zakoupit.

Kompletní příklad

Níže najdete ucelený příklad, který ukazuje to, co jsme si řekli a navíc přidává některé zajímavé věci pro podporu budoucího refaktoringu.

Shrnutí

Event Bus může tedy pro nás být poměrně jednoduchým způsobem, jak distribuovat události napříč aplikací a komponentami ve vertikální rovině i komponentami mezi sebou na úrovni horizontální. Data nám protékají vždy shora dolů. Máme pak kontrolu nad tokem dat, což se nám při dalším rozvoji aplikace vyplatí.


  1. V malých aplikacích ale ve skutečnosti budete stejně používat jQuery, vy "neznavueové". ↩︎