Praktické príklady s Vue – 4/x
Tento príklad je už je trochu iný. Kým prvé tri viac predstavovali, ako vysvetľovali, toto je prvý z príkladov, ktoré menej ukážu, ale o to viac vysvetlia. A tento krát je kód aj okomentovaný, aby bol text dával o to väčší zmysel.
Asynchrónny komponent
Pointou tohoto príkladu je vysvetlenie, ako sa efektívne vysporiadať s definovaním komponentov v SPA. Single-page aplikácia nutne neznamená mať aj definície komponentov v jednom súbore. Bavíme sa o single-page, nie single-file… Vyhádzaním definícií komponentov do externých súborov získate neskutočne mnoho … napríklad „objektový prístup“ – Fero bude opravovať svoj zmršený komponent, Jožo zasa svoj a nie aby druhý čakal kým prvý neskončí v jedinom súbore. Ďalej tým získate rýchlejšie načítanú svoju SPA. Len tie komponenty ktoré je nutné vykresliť na konkrétnej podstránke budú natiahnuté na pozadí – proste asynchrónne komponenty sa nahrávajú až keď ich je treba. A tie ktoré budú nahrané, ostanú nakešované – žiadne nahrávanie stále dokola pri vrátení sa na už navštívenú podstránku. A také niečo, ako zakomponovať do SPA loader animation kým sa nahrá obsah takéhoto asynchrónneho komponentu / stránky, vôbec nemusíte riešiť po svojom. Nižšie v kóde uvidíte, ako to zas raz rieši za vás Vue priam trápne jednoducho…
<style>
/* Predtým ako vložíš nový element do DOM, pridaj mu túto triedu */
.fade-enter { opacity: 0; transform: translateY(30px); }
/* A aj túto triedu */
.fade-enter-active { transition: all 0.4s; }
/* Po prídaní týchto tried je element vložený do DOM, ale priesvitný
a posunutý nadol. Lenže hneď po vložení do DOM, jeden frame na to,
sa mu zároveň odoberie enter trieda. Takže štýl elementu sa vráti
na default: nepriesvitný a neposunutý. Avšak trieda enter-active mu
ostala a je v nej predsa transition! Takže sa štýl nevráti na default
skokom, ale rozanimovane...
/* ------------------------------------------------------------------------ */
/* Predtým ako odoberieš tento element z DOM, pridaj mu túto triedu */
.fade-leave-active { transition: all 0.4s; }
/* Nie zároveň, ale jeden frame na to, mu pridaj aj túto triedu */
.fade-leave-to { opacity: 0; transform: translateY(-30px); }
/* Tu je postup nasledovný: pred odobraním elementu z DOM sa mu pridá
leave-active trieda. Jeden frame na to sa mu následne prídá aj
leave-to trieda. Čiže sa zmení štýl elementu na priesvitný a posunutý
nahor, avšak zasa nie skokom, lebo predtým sa mu triedou leave-active
pridal transition, takže aj v tomto prípade zmena na nový štýl prebehne
rozanimovane... */
</style>
<div id="app">
Príklad reštartujte prepnutím<br>
napríklad ná záložku HTML a následne<br>
naspäť na záložku Result.
<!-- Transition komponent zabezpečí, že keď sa child komponent
bude meniť, či už pridávať, alebo odoberať, tak predtým ako
sa ten vnorený element pridá, alebo vymaže z DOM, najskôr
na ňom prebehnú CSS animácie, pridávaním, alebo odoberaním
príslušných tried, napárovaných cez name atribút. A mode
atribút je príkaz, aby sa pri zmene child komponentu najkôr
odobral starý, vrátane počkania na jeho animáciu a až potom
vložil do DOM nový element, na ktorom následne tiež môže,
či nemusí prebehnúť animácia. Skúste ten atribút vymazať
a pochopíte... -->
<transition name="fade" mode="out-in">
<!-- Vykresli komponent, ktorý je špeciálny tým, že v tomto
súbore nie je jeho definícia. -->
<async txt="TEST" :num="12" :obj="{key1: 'val1'}" :arr="['Bu!']"></async>
</transition>
</div>
<script src="https://unpkg.com/vue@2.4.4/dist/vue.js"></script>
<script>
/* Toto je akože definícia komponentu uložená v externom
súbore v json tvare. */
var json = {
props: ['txt', 'num', 'obj', 'arr'],
template: '<p>{{txt}}, {{num}}, {{obj.key1}}, {{arr[0]}}</p>'
}
// Pomocná funkcia slúžiaca na nahrávanie definície komponentov.
function loadFromFile(uri) {
/* Parameter uri tu však odignorujeme a trvanie nahrávania
komponentu nasimulujeme so setTimeout */
return new Promise(function (res, rej) {
setTimeout(function () {
res(json)
}, 3000)
})
}
/* Tento lokálne registrovaný komponent bude zobrazený počas
nahrávania obsahu asynchrónneho komponentu. */
var loader = {
template: '<p>Nahrávam...</p>' // Alebo div so spinnerom...
}
/* Tento komponent, vrátane šablóny bude nahraný asynchrónne
zo súboru pomocou funkcie loadFromFile. Ale za a) len ak ho
vôbec bude treba vykresliť a za b) keď sa nahrá, ostane
nakešovaný. Žiadne znovu nahrávanie. */
Vue.component('async', () => ({
// Pozor, funkcia loadFromFile musí vrátiť Promise.
component: loadFromFile('path-to-component'),
// Kým sa nahrá obsah z externého súboru, zobraz komponent loader.
loading: loader,
// Ale loader zobraz len ak nahrávanie potrvá dlhšie ako 0.2 sekundy.
delay: 200
}))
new Vue({
el: '#app'
})
</script>
[iframe src=“https://jsfiddle.net/provuecateur/oh6b5od9/embedded/result,html,css,js/“ width=“100%“ height=“600″]