Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Vue.js techtalk: Advanced

Vue.js techtalk: Advanced

Let's talk about how to get Router and Vuex data store working for a simple app - API Inspector

Jakub Mikulas

February 23, 2017
Tweet

More Decks by Jakub Mikulas

Other Decks in Technology

Transcript

  1. We have the basic scheme • 2 columns • le,

    one with naviga4on is always visible => it'll be our skeleton • right one will be changing depending on what we want to see => we will need a router • Empty state is our default, because we don't have anything to show now
  2. Let's add something to the le0 • I'm not limited

    by any exis2ng API, so I can do whatever I want now • It will be a list of recent calls => array • we don't have much choice how to render list => v-for="call in calls" to iterate
  3. Create a JSON with some dummy data and import it

    { "method": "get", "resourceName": "Something good", "responseCode": 200 },
  4. // App.vue import calls from './calls.json'; export default { name:

    'inspector', data() { return calls; }, }; In template: <div class="aside__list"> <div v-for="call in calls">{{call.resourceName}}</div> </div>
  5. // App.vue import calls from './calls.json'; export default { name:

    'inspector', data() { return calls; }, }; In template: <div class="aside__list"> <!-- This sucks --> <div v-for="call in calls">{{call.resourceName}}</div> </div>
  6. <!-- call.vue --> <template> <div class="call"> <div class="call__nameWrap"> <div class="call__name">{{call.resourceName}}</div>

    <div class="call__meta">Code: <strong>{{call.responseCode}}</strong></div> </div> <div class="call__method" :class="'call__method--' + call.method">{{call.method}}</div> <div class="call__arrow"></div> </div> </template> <script> export default { name: 'call', props: { call: Object, }, }; </script>
  7. // App.vue import call from './components/call'; // Import the component

    import calls from './calls.json'; export default { name: 'inspector', data() { return calls; }, components: { call, // Register the component }, }; In template: <div class="aside__list"> <call v-for="call in calls" /> </div>
  8. <!-- call.vue --> <template> <div class="call"> <div class="call__nameWrap"> <div class="call__name">{{call.resourceName}}</div>

    <div class="call__meta">Code: <strong>{{call.responseCode}}</strong></div> </div> <div class="call__method" :class="'call__method--' + call.method">{{call.method}}</div> <div class="call__arrow"></div> </div> </template> <script> export default { name: 'call', props: { call: Object, }, }; </script>
  9. // App.vue import call from './components/call'; // Import the component

    import calls from './calls.json'; export default { name: 'inspector', data() { return calls; }, components: { call, // Register the component }, }; In template: <div class="aside__list"> <call v-for="call in calls" :call="call" /> </div>
  10. Let's make the le, naviga1on working • we need some

    iden+fier for links, so I've added id to the calls.json • let's use standard <router-link> which transforms into standard <a> (so "Open in a new panel" works in your browser) <!-- components/call.vue --> <div class="call"> <!-- from this --> <router-link class="call" :to="{ name: 'Call', params: { id: call.id } }"> <!-- ... --> </router-link>
  11. // router.js export default new Router({ routes: [ { path:

    '/', name: 'Empty', component: empty, }, { path: '/call/:id', name: 'Call', component: callDetail, <!-- new component --> }, ], });
  12. Now let's get the selected data from the le2 to

    the right part it's a good *me to use Vuex Vuex is a state management pa.ern + library
  13. Think about it as something that will take away the

    guess work from frontend. It's right there in Vue Devtools
  14. Step 1: create a store and move the sta2c array

    of calls to Vuex // store.js import Vue from 'vue'; import Vuex from 'vuex'; import calls from './calls.json'; Vue.use(Vuex); // Initialize export default new Vuex.Store({ state: { calls, }, });
  15. Step 2: Connect Vuex store to the app // main.js

    import Vue from 'vue'; import App from './App'; import store from './store'; import router from './router'; new Vue({ el: '#app', router, store, // Add Vuex store to the app template: '<App/>', components: { App }, });
  16. Step 3: get reac,ve data from the store // App.vue

    import call from './components/call'; import calls from './calls.json'; export default { name: 'inspector', data() { return calls; }, components: { call, }, };
  17. Step 3: get reac,ve data from the store // App.vue

    import call from './components/call'; export default { name: 'inspector', computed: { calls() { return this.$store.state.calls; }, }, components: { call, }, };
  18. This image might be too complicated But takeaway is that

    important bits are happening in Vuex
  19. Components can't write to the state! They can only issue

    orders to the store. Like: "do this ac6on" or "do this ac6on, with this value" Components are just saying eg.: • User did something, go fetch new data • User did something, change your data
  20. Vuex store have 4 main parts: • state: that's just

    serializable Object of current state • ge&ers: read-only helpers that can transform value (eg. filter an array). They get their data from read-only state. Example coming up. • muta*ons: only way to write to the state. Simple synchronous funcFons that can modify the state. • ac*ons: larger, possibly asynchronous or chained funcFons, that can start a mutaFon. Imagine AJAX call, that on success passes data to the mutaFon to do the state write.
  21. Let's create a ge+er that we can use to get

    data to the right side. Why ge#er? Because its value is changing depending on state of the applica6on (different routes will want to see different data on the right)
  22. Let's do it by saving current route to Vuex. We

    could do it manually, by crea:ng muta:ons, but there is an official helper vuex- router-sync. This adds current route Object to Vuex state. // main.js import Vue from 'vue'; import { sync } from 'vuex-router-sync'; // import the package import App from './App'; import store from './store'; import router from './router'; sync(store, router); // sync Store with Router, done new Vue({ el: '#app', router, store, template: '<App/>', components: { App }, });
  23. // store.js import Vue from 'vue'; import Vuex from 'vuex';

    import calls from './calls.json'; Vue.use(Vuex); export default new Vuex.Store({ state: { calls, showExample: false, }, getters: { activeCall: state => state.calls.find(c => c.id === state.route.params.id), }, });
  24. export default { name: 'callDetail', computed: { call() { return

    this.$store.getters.activeCall; }, }, };
  25. Recap • Router is just a plain Object • Vuex

    store is just a plain Object - ge7ers, muta:ons and ac:ons are just simple func:ons => it's simple to test • Vuex improves controller readability