Připravil: Ing. Jiří Lýsek, Ph.D. Verze: 16. 4. 2019 Webové aplikace ES6, Vue
strana 2 ES6, ES7... ES NEXT Nová/rozšířená syntaxe Mnoho vylepšení Není podporováno ve všech prohlížečích https://caniuse.com/ Nutná transpilace - https://babeljs.io/
strana 3 Novinky let a const Náhrada/rozšíření definice proměnné var let definuje platnost jen pro daný pár { a dále do hloubky for(var i ) VS for(let i ) const je vhodné pro proměnné, které mají pevný obsah Pozor na objekty
strana 4 Novinky for of Pro iteraci přes pole let p = [1,2,3,4,5]; for(let h of p) { console.log(h);
strana 5 Novinky výchozí parametry Pro funkce i metody function fce(p1, p2 = 123) {...
strana 6 Novinky třídy class Trida extends JinaTrida { constructor(p1, p2 = 123) { this.p1 = p1; this.p2 = p2; metoda() {
strana 7 Novinky arrow funkce (p1, p2) => { Nemění obsah this při zanoření do { class Pocitadlo { constructor(btn) { this.cnt = 0; btn.onclick = () => { this.cnt++; function() { by mělo jiné this
strana 8 Novinky zkrácené metody a vlastnosti var cokoliv = 132; var o = { f: function() {..., cokoliv: cokoliv var o = { f() {..., cokoliv Výhodné pro poslání dat v JSON
strana 9 Novinky destructuring assignment Vytažení hodnot z pole function f() { return [1,2,3,4,5,6] [a, b,...rest] = f(); //a=1, b=2, rest=[3,4,5,6]
strana 10 Novinky template string Dosazování proměnných do řetězce Dobré pro stavbu URL nebo šablony Podpora víceřádkových řetězců var x = 876; var url = `api?param=${x`;
strana 11 Novinky zbytek Generátory a yield async a await Souvislost s třídou Promise Anotace typů u metod Více na https://babeljs.io/
strana 12 ES6 modules Používá klíčová slova import a export/export default Nepoužitelné v browseru Nutný bundler Pozor na NodeJS require() a module.exports A pozor na podobnost s knihovnou require.js (ta je pro browser)
strana 13 ES6 modules Hlavní skript: Název si volíte (řeší kolize) import Trida from 'file'; let t = new Trida(); t.method(); Bez koncovky Podobné jako v Pythonu Modul ve file.js: export default class { constructor() { method() {
strana 14 ES6 modules Hlavní skript: import { f1, f2 from 'file'; f1(); f2(); Modul ve file.js: export let f1 = () => {... ; export let f2 = () => {... ; Nebo var
strana 15 Vue komponenty komunikace Komunikace mezi komponentami Potomek vyvolá událost Rodič může volat metody Rodič může poslat data přes atribut <potomek @udalost="udalost" :data="vstup" ref="nazev">
strana 16 Vue komponenty komunikace Rodič parent.vue <template> <div> <button @click="inc">inc</button> <counter ref="c" :def="10" @updated="upd"></counter> </div> </template> <script> import Counter from "./counter"; export default { methods: { inc() { this.$refs.c.inc();, upd(v) { console.log("updated", v);, components: { counter: Counter, </script> Potomek counter.vue <template> <div>{{c</div> </template> <script> export default { props: ["def"], data() { return { "c": 0, methods: { inc() { this.c++; this.$emit("updated", this.c);, mounted() { this.c = this.def; </script>
strana 17 Vue komponenty komunikace Rodič parent.vue <template> <div> <button @click="inc">inc</button> <counter ref="c" :def="10" @updated="upd"></counter> </div> </template> <script> import Counter from "./counter"; export default { methods: { inc() { this.$refs.c.inc();, upd(v) { console.log("updated", v);, components: { counter: Counter, </script> Výchozí hodnota Potomek counter.vue <template> <div>{{c</div> </template> <script> export default { props: ["def"], data() { return { "c": 0, methods: { inc() { this.c++; this.$emit("updated", this.c);, mounted() { this.c = this.def; </script>
strana 18 Vue komponenty komunikace Rodič parent.vue <template> <div> <button Klik @click="inc">inc</button> <counter ref="c" :def="10" @updated="upd"></counter> </div> </template> <script> import Counter from "./counter"; export default { methods: { inc() { this.$refs.c.inc();, upd(v) { console.log("updated", v);, components: { counter: Counter, </script> Potomek counter.vue <template> <div>{{c</div> </template> <script> export default { props: ["def"], data() { return { "c": 0, methods: { inc() { this.c++; this.$emit("updated", this.c); Metoda, mounted() { this.c = this.def; </script> Aktualizace view
strana 19 Vue komponenty komunikace Rodič parent.vue <template> <div> <button @click="inc">inc</button> <counter ref="c" :def="10" @updated="upd"></counter> </div> </template> <script> import Counter from "./counter"; export default { methods: { inc() { this.$refs.c.inc();, upd(v) { console.log("updated", v);, components: { counter: Counter, </script> Metoda Událost Potomek counter.vue <template> <div>{{c</div> </template> <script> export default { props: ["def"], data() { return { "c": 0, methods: { inc() { this.c++; this.$emit("updated", this.c);, mounted() { this.c = this.def; </script>
strana 20 Vue komponenty sloty Pro vložení obsahu definovaného rodičem do potomka Úprava vzhledu potomka Lze pojmenovat
strana 21 Vue komponenty sloty Rodič parent.vue <template> <paginate ref="p" :size="pagesize" @page="filter"> <div v-for="i of visible"></div> </paginate> </template> <script> import Paginate from './paginate'; export default { data() { return { pagesize: 3, visible: [], items: [], methods: { filter() {..., mounted() { this.filter();, components: { paginate: Paginate </script> Potomek paginate.vue <template> <div> <slot></slot> <button @click="prev">p</button> <button @click="next">n</button> </div> </template> <script> export default { props: ['size'], data() { return { start: 0, methods: { getstart() {..., prev() { this.$emit("page");, next() { this.$emit("page"); </script>
strana 22 Vue komponenty sloty Rodič parent.vue <template> <paginate ref="p" :size="pagesize" @page="filter"> <div v-for="i of visible"></div> </paginate> </template> <script> Obsah v šabloně se vloží do slotu potomka import Paginate from './paginate'; export default { data() { return { pagesize: 3, visible: [], items: [], methods: { filter() {..., mounted() { this.filter();, components: { paginate: Paginate </script> Potomek paginate.vue <template> <div> <slot></slot> <button @click="prev">p</button> <button @click="next">n</button> </div> </template> <script> export default { props: ['size'], data() { return { start: 0, methods: { getstart() {..., prev() { this.$emit("page");, next() { this.$emit("page"); </script>
strana 23 Vue komponenty sloty Rodič parent.vue <template> <paginate ref="p" :size="pagesize" @page="filter"> <div v-for="i of visible"></div> </paginate> </template> <script> import Paginate from './paginate'; export default { data() { return { pagesize: 3, visible: [], items: [], methods: { filter() {..., mounted() { this.filter();, components: { paginate: Paginate </script> Události zařídí přepsání viditelných dat Potomek paginate.vue <template> <div> <slot></slot> <button @click="prev">p</button> <button @click="next">n</button> </div> </template> <script> export default { props: ['size'], data() { return { start: 0, methods: { getstart() {..., prev() { this.$emit("page");, next() { this.$emit("page"); </script> Klik na tlačítko
strana 24 Vue komponenty provide/inject Mechanismus pro sdílení "objektu" V hlavní komponentě se nastaví provide V libovolné zanořené komponentě se podle názvu zpřístupní v inject https://vuejs.org/v2/api/#provide-inject
strana 25 Vue komponenty provide/inject Hlavní komponenta main.js const messagebus = new Vue(); new Vue({ el: '#app', provide: { messagebus, components: {App, template: '<App/>' ); Libovolný potomek export default { inject: ['messagebus'], methods: { emit() { this.messagebus. $emit(...);
strana 26 Vue globální události Je nutné zaregistrovat message bus Je to obyčejná prázdná komponenta Distribuce do komponent přes ES6 moduly pomocí provide inject mechanismu let messagebus = new Vue(); messagebus.$emit("ev", param); messagebus.$on("ev", () => {);
strana 27 Vue globální události Odesílatel <template> <div> <input type="text" v-model="payload"> <button @click="emit">emit</button> </div> </template> <script> export default { inject: ['bus'], data() { return { payload: '', methods: { emit() { this.bus.$emit('ev', this.payload); </script> Příjemce <template> <div>{{msg</div> </template> <script> export default { inject: ['bus'], data() { return { msg: '', methods: { receive(m) { this.msg = m;, mounted() { this.bus.$on('ev', this.receive); </script>
strana 28 Vue globální události Odesílatel <template> <div> <input type="text" v-model="payload"> <button @click="emit">emit</button> </div> </template> <script> export default { inject: ['bus'], data() { return { payload: '', methods: { emit() { this.bus.$emit('ev', this.payload); </script> Klik Vyvolána událost Příjemce <template> <div>{{msg</div> </template> <script> export default { inject: ['bus'], data() { return { msg: '', methods: { receive(m) { this.msg = m;, mounted() { this.bus.$on('ev', this.receive); </script> Zobrazení zprávy
strana 29 Vue router https://router.vuejs.org/en/ Řeší výběr komponenty podle URL Konfigurace v kódu aplikace HTML5 režim Nutná podpora mod_rewrite, jinak hash Routy je možné pojmenovat Nastavení meta informací Např. pro přihlášené uživatele
strana 30 Vue router - komponenty router-view Slouží k zobrazení komponenty podle URL <router-view></router-view> router-link Slouží k navigaci mezi komponentami Odkazovat pomocí názvu cesty <router-link :to="{name: ' '"> odkaz </router-link>
strana 31 Vue router události router.beforeeach((to, from, next) => { //přesměrovat jinam next({name: '...'); //zabránit navigaci next(false); //normálně pokračovat next(); );
strana 32 Vue router navigace v kódu Slouží pro navigaci vyvolanou jinak než klikem na odkaz - "přesměrování" export default { methods: { presmeruj() { this.$router.push({ name: '...' ); Je potřeba zaregistrovat router do hlavní/horní komponenty
strana 33 Vue router parametry cesty { path: '/.../:id', name: '...', component: Komponenta Definice cesty Navigace z odkazu <router-link :to="{name: '...', params: { id: 5 "> odkaz Navigace v kódu </router-link> this.$router.push({ name: '...', params: { id: 10 ); mounted() { console.log(this.$route.params.id); Přístup k hodnotě v cílové komponentě $route VS $router!!!
strana 34 Vuex Knihovna pro globální stav aplikace https://vuex.vuejs.org/en/ Přes ES6 moduly Dá se registrovat do hlavní komponenty Komponenty by neměly držet stav Stav = přihlášený uživatel, zobrazené položky, rozpracovaný dokument,... To co je společně použité ve více komponentách
strana 35 Vuex store stav import Vuex from 'vuex'; import Vue from 'vue'; Vue.use(Vuex); + registrace do hlavní komponenty aplikace v main.js export default new Vuex.Store({ state: { count: 0 );
strana 36 Vuex store mutace export default new Vuex.Store({ state: { count: 0, mutations: { increment(state, val) { state.count += val; ); Synchronní úprava stavu //v kódu komponenty this.$store.commit('increment', 5);
strana 37 Vuex store akce export default new Vuex.Store({ state: {..., mutations: {..., actions: { increment(context, val) { axios.post(...,...).then(() => { context.commit('increment', val); ); ); //v kódu komponenty this.$store.dispatch('increment', 5); Asynchronní akce
strana 38 HTTP komunikace Axios Vue přímo neobsahuje HTTP knihovnu Je možné použít např. Axios Založené na Promise Dobrá práce s REST API https://github.com/axios/axios Nebo jinou HTTP knihovnu pro REST Nebo Fetch API jquery ne, je příliš obsáhlé a není dobré pro REST
strana 39 HTTP komunikace Axios import axios from 'Axios'; const axios = Axios.create(); axios.defaults.baseurl = 'http...'; Vue.prototype.$http = axios; this.$http.get(url).then() this.$http.post(url, data).then() this.$http.put(url, data).then() this.$http.delete(url).then()
strana 40 Registrace do hlavní komponenty import router from './router'; import store from './store'; new Vue({ router, store,... ).$mount('#app');
strana 41 Checkpoint Které ES6 syntaktické novinky už jsou podporovány v běžných prohlížečích? Jaké jsou možnosti komunikace mezi komponentami? Stahovat data z REST API v komponentách nebo ve store? Jaký je rozdíl mezi mutací a akcí?