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″]