Jak jsem si zamiloval Vue Class Component

Ve Vue.js 2.6 už mám napsanou zhruba desítku aplikací + několik dalších modulů do stávajících projektů. Jelikož asi 20 let vyvíjím projekty hlavně v PHP, kde jsem postupně přešel na OOP, chci stejné principy využívat také v Javascriptu (Vue.js). Když jsem objevil, že existuje něco jako Vue Class Component, tak mě to samozřejmě zaujalo. Chvíli mi trvalo, než jsem v to získal důvěru a začal používat. Je to jedna z možností, volitelná, nepovinná. Někomu se třídy nelíbí a nemusí je vůbec používat, dá se progrmaovat bez nich. Ale s třídama je to to „pravé objektové“, to je můj styl, ve kterém jsem se našel a plně mi vyhovuje.

Vue Class Component je knihovna, která umožňuje psát class-style syntax. Nepotřebuje Typescript, funguje i v čistém JS.

Použití Component

Nejdříve si naimportuji Component. Samozřejmě předtím je třeba nainstalovat závislost (podle toho, jakým způsobem si instalujete do package.json, https://github.com/vuejs/vue-class-component). Já jsem si oblíbil vue ui (v prohlížeči vyberu projekt , vyhledám název balíčku a instaluji). Ale jde to samozřejmě klasicky otevřít terminal a spusti npm i vue-class-component nebo yarn install …

import Component from 'vue-class-component'

A pak definice komponenty jako třída rozšířující třídu Vue s pomocí dekorátoru.

@Component
export default class NazevKomponenty extends Vue {
...
}

Výhody použití Vue Class Component proti klasickému JS objektu

  • lepší čitelnost kódu
  • možnost používat společně s Typescript
  • další jsem zatím neobjevil (ale píše se o vuex-class)

Lepší čitelnost oceňuji, třída nemá tolik členů jako v JS objektu, nemusím zanořovat data a psát je jako funkci, místo computed použiju intuitivně get/set, methods není třeba vůbec, metody píšu kde chci v třídě. Definice „components“ a „props“ se píšou jako options v dekorátoru namísto v definici třídy. Dává to smysl, je to vlastně jen jednorázová konfigurace té komponenty. Ale co watch ? Neřeším. Aby v tom nebyl bordel a dalo se to všechno psát v definici třídy, tak nějaký borec kaorun343 vytvořil vue-property-decorator. Property decorator umožňuje psát @Watch atd. v definici třídy podobně jako funguje dekorátor Component.

A použitím třídy získávám možnost používat dědičnost tříd a dekorátory všude, to se vyplatí.

Jako logický krok dále považuji použití TypeScriptu, když už používám class-style, tak jsem rovnou přepsal vše do ts. Typescript umožňuje používat OOP principy. O tom napíšu v dalším článku Jak přidat Typescript.

Vuexmodule decorators

Zdroj: https://www.npmjs.com/package/vuex-module-decorators

VuexModule je třída, ze které rozšířením vytvářím moduly pro Vuex store. VuexModule se dá používat také bez store, ale to zatím nepoužívám.

Další možností je použití jen Vuex class např. zde. https://bezkoder.com/vuex-typescript-jwt-auth/. Ale to zatím nepotřebuji. Vuex Module Decorators se zdají být dostatečné pro mojí potřebu.

npm i vuex-module-decorators -D

import { VuexModule, Module, Mutation, Action } from 'vuex-module-decorators';
@Module({ namespaced: true })

VuexModule: dekorátory Mutation a Action

Pokud mám v aplikaci spoustu modulů např. moduly user.ts, order.ts, firm.ts a mutace přiřazují různé typy dat o uživateli, formě, objednávce služeb apod., potřebuji ohlídat, jestli se někde v mutacích nepřiřazuje např. number do string apod. Na to potřebuji mít modul napsaný v Typescript, aby mě TS kompilátor při kompilaci na chybu upozornil.

Anotováním setovací funkce dekorátorem @Mutation udělám z funkce mutaci, to samé když potřebuji udělat z update funkce akci, použiju dekorátor @Action. Díky dekorátorům je psaní kódu jednodušší a přehlednější.

Proč používat getModule

Accessor getModule umožňuje bezpečně nahradit volání mutací a akcí místo obvyklého „store.commit“ a „await store.dispatch“. Do konstanty např. postModule si načtu modul z Vuex store přes getModule a pak z ní mohu tahat state, getters, mutation, action.

const myMod = getModule(MyModule)
myMod.someField //works
myMod.someOtherField //Typescript will error, as field doesn't exist

Jak je vidět na příkladu, tak pokud bych omylem pracoval někde s neexistující hodnotou modulu, tak mě TypeScript na to upozorní ! getModule má jako druhý parametr store, takže umožňuje přidávat moduly do store po vytvoření prázdného store ? To je složité, tolik možností, proč ?

V namespaced modulu mohu registrovat fci také „globálně“ přidáním parametru root: true, ale to nevím zatím k čemu bych použil. Moduly se dají registrovat do store dynamicky až po vytvoření store za běhu aplikace, ale to také neumím zatím využít.