Intro to VueJS

60187fe0ab07ea5a46572a3ab05f61dd?s=47 Matt Stauffer
February 22, 2017

Intro to VueJS

Casual meetup intro to VueJS. Scrapped together in a few hours for Gainesville JS (http://gnvjs.com/)

Many of the examples are just from the docs--consider this a draft of a potential future conference talk.

60187fe0ab07ea5a46572a3ab05f61dd?s=128

Matt Stauffer

February 22, 2017
Tweet

Transcript

  1. Introducing Vue.JS (A casual introduction)

  2. What is Vue?

  3. What is Vue? It's a JavaScript framework. It has a

    Virtual DOM and composable, reactive components. Its core is small and works well with companion libraries for routing, global state, and HTTP requests. It's light, fast, and flexible.
  4. How is it different from ... • jQuery? (jQuery is

    not a framework, it's a library) • Knockout? (more modern, lifecycle hooks, better component management, more active development) • AngularJS? (simpler, faster, less opinionated, more flexible, one-way data binding) • React? (faster, simpler tooling, and prefers HTML/CSS over JavaScript for templates) • Ember? (simpler, less opinionated, no need for Ember objects, faster)
  5. How is it different from ... Learn more: Vue's internal

    comparison with other frameworks https://vuejs.org/v2/guide/comparison.html
  6. What does the syntax look like? <div id="app"> {{ message

    }} </div> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script> new Vue({ el: '#app', data: { message: 'Hello World!' } }) </script>
  7. What did that just do? • Create a Vue instance

    that's bound to a div with an id of "app" • Interpret the contents of that div as its template • Read Mustache-style syntax ({{ message }}) and in response echo out the contents of the "message" variable
  8. Reactive data

  9. Reactive data The data in the previous example is "reactive"—if

    we change the message it'll update the template: <script> var vm = new Vue({ el: '#app', data: { message: 'Hello World!' } }) // here, or in your console: vm.message = 'Goodbye World!' // ... template will update
  10. Data binding with v-model <div id="app"> <input v-model="message" placeholder="edit me"><br>

    <p>Message is: {{ message }}</p> </div> <script> new Vue({ el: '#app', data: { message: '' } }) </script>
  11. V-model in action

  12. Options for templating

  13. What else can we do in our templates? • You

    could write your own render functions and even use JSX • mustache: {{ propertyName }} • v-bind for attributes: <div v-bind:id="superId"></div> • expressions: {{ signedUp ? 'Cancel' : 'Sign up' }}, <div v-bind:disabled="status == 'published'"> • filters: {{ slug | capitalize }}
  14. Vue Directives: v-* • v-if / v-else: <p v-if="message">{{ message

    }}<p> • v-show: <p v-show="message">{{ message }}</p> • v-for: <li v-for="dog in dogs">{{ dog.name }}</li>
  15. Vue Directives: v-* (continued) • v-on:event: <a v-on:click="clickHandler">Do stuff</a> •

    modifiers: v-on:submit.prevent="onSubmit" • v-bind:class: <div v-bind:class="{ className: prop, otherClassName: propTwo == 'published' }">
  16. Methods

  17. Methods Defining repeated behavior once, with a name. <div id="app">

    {{ showThing() }} </div> <script> new Vue({ el: '#app', data: { message: 'Hello World!' }, methods: { showThing: function () { return `THING SHOWN: ${this.message}` } } }) </script>
  18. Methods (continued) ... also can be used anywhere an expression

    is accepted in Vue templates. So this: <div id="app"> <p><button v-on:click="counter++">[+]</button><br>{{ counter }}</p> </div> <script> new Vue({ el: '#app', data: { counter: 0 } }) </script>
  19. Methods (continued) ... can become this: <div id="app"> <p><button v-on:click="increment">[+]</button><br>{{

    counter }}</p> </div> <script> new Vue({ el: '#app', data: { counter: 0 }, methods: { increment: function () { this.counter++ } } }) </script>
  20. Methods (continued) ... or this: <div id="app"> <p><button v-on:click="increment(2)">[+]</button><br>{{ counter

    }}</p> </div> <script> new Vue({ el: '#app', data: { counter: 0 }, methods: { increment: function (amount) { this.counter += amount } } }) </script>
  21. Interlude: shortcuts Commonly used directives often have shortcuts. • v-on:click

    can be represented as @click <a @click="doThing">click me</a> • v-bind:href can be represented as :href <my-component :propertyName="propertyValue"></my-component>
  22. The event object in methods <div id="app"> <button @click="doIt">Do it.</button>

    </div> <script> new Vue({ el: '#app', methods: { doIt: function (event) { console.log(event.target) } } }) </script>
  23. Computed properties

  24. Computed properties Like decorators with magical listeners built in. Any

    property based on the content of another. What's different between a method and a computed property? Methods run every they're re-requested; computed properties are cached based on their dependencies, and only change when their dependencies change.
  25. Computed properties (continued) <div id="app"> <p>{{ messageReversed }}</p> </div> <script>

    new Vue({ el: '#app', data: { message: 'Howdy!' }, computed: { messageReversed: function () { return this.message.split('').reverse().join('') } } }) </script> // @todo better example
  26. Computed properties (continued) Are "get"-only by default, but can be

    both get and set: // ... computed: { fullName: { // getter get: function () { return this.firstName + ' ' + this.lastName }, // setter set: function (newValue) { var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } } // ... // @todo make this real example
  27. Lifecycle hooks • Callback hooks on given events for each

    component • beforeCreate, created • beforeMounted, mounted • updated • destroyed
  28. None
  29. Lifecycle hooks (continued) new Vue({ el: '#app', data: { topics:

    [] }, mounted: function () { this.topics = ajaxMethodFromElsewheregettingTopics() } })
  30. A few caveats (with Vue's reactive model) • If you

    set props on a instance after it starts up, those props won't be reactive (vm.newProperty = 'please-track-me') • If you're setting a prop of an array/object, you have to use Vue.set in order for it to be tracked/reactive Vue.set(myArray, itemIndex, value)
  31. Vue Components

  32. Defining and using Vue components Each component is a little

    Vue instance. Defining a global component named "todo-item": Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) <ol> <todo-item v-for="item in todos" v-bind:todo="item"></todo-item> </ol>
  33. Defining and using Vue components You can also define components

    locally: var TodoItem = { props: ['todo'], template: '<li>{{ todo.text }}</li>' } new Vue({ // ... components: { 'todo-item': TodoItem } })
  34. Vue component caveats • data property must be a method,

    not an object: Vue.component('whatever', { // ... data: function () { return { propName: true } } }) • If your template is in HTML, you may have to use <td is="todo-item"></td>
  35. Props, events, and sync

  36. Props, events, and sync Pass property from parent to child

    using props. Send changes from child to parent using custom events. "Props down, events up"
  37. Passing props into a component Pass data into a component

    as a "prop" on the component instance— sort of like a constructor property. <my-component message="Do it!"></my-component> Vue.component('banner', { props: ['message'], template: '<li>{{ message }}</li>' })
  38. Passing dynamic props If the data is pulled from data

    on the parent, it's "dynamic": <my-component v-bind:message="banner"></my-component> <!-- Shortcut: --> <my-component :message="banner"></my-component>
  39. Side note: variable casing CamelCase in the JavaScript, kebab-case in

    HTML.
  40. Emitting and listening to custom events Vue.component('terms-of-service', { template: '<button

    @click="accept">Accept</button>', methods: { accept: function () { this.$emit('accept-terms-of-service') } } }) new Vue({ el: '#app', methods: { acceptTOS: function () { // ... } } }) <div id="app"> <terms-of-service v-on:accept-terms-of-service="acceptTOS"></terms-of-service> </div>
  41. Passing data with custom events Vue.component('terms-of-service', { template: '<button @click="accept">Accept</button>',

    methods: { accept: function () { this.$emit('accept-terms-of-service', {'somedata': 'here'}) } } }) new Vue({ el: '#app', methods: { acceptTOS: function (data) { // ... } } })
  42. Using a new Vue instance as an event bus var

    bus = new Vue() // in component A's method bus.$emit('id-selected', 1) // in component B's created hook bus.$on('id-selected', function (id) { // ... })
  43. Sync It's old. Don't use it anymore.

  44. Slots

  45. Simple slot <!-- Child component "my-component" with slot --> <div>

    <h2>Title of child</h2> <slot> Fallback content here </slot> </div> <!-- Parent component passes data to slot --> <div> <h1>Title of parent</h1> <my-component> <p>This is some original content</p> </my-component> </div>
  46. Named slot <!-- child component "app-layout" --> <div class="container"> <header>

    <slot name="header"></slot> </header> <main> <slot></slot> </main> </div> <!-- parent --> <app-layout> <h1 slot="header">Here might be a page title</h1> <p>A paragraph for the main content.</p> </app-layout>
  47. Other ways to load Vue vue-cli Simple CLI tool for

    scaffolding Vue projects https://github.com/vuejs/vue-cli Default templates: - Webpack - Browserify - Simple HTML
  48. Not going to cover in depth:

  49. Routing Vue-Router: http://router.vuejs.org/ https://github.com/mattstauffer/suggestive

  50. State management If event bus isn't good enough, check out

    Redux or Vuex https://vuex.vuejs.org/
  51. Testing Many options, but first recommendation is Karma. https://vuejs.org/v2/guide/unit-testing.html

  52. Prerendering For SEO, marketing, etc. you can build pages to

    HTML: https://github.com/chrisvfritz/prerender-spa-plugin
  53. Server side rendering Actual live SSR using vue-server-renderer https://vuejs.org/v2/guide/ssr.html

  54. Mixins Like mixins in Ruby or traits in PHP; bring

    in a group of properties. // define a mixin object var myMixin = { created: function () { this.hello() }, methods: { hello: function () { console.log('hello from mixin!') } } } // define a component that uses this mixin var Component = Vue.extend({ mixins: [myMixin] }) var component = new Component() // -> "hello from mixin!"
  55. Single-file syntax (Vueify) // component.vue <template> <div class="my-component"> {{ message

    }} </div> </template> export default { data: { message: 'Hello World!' } } <style lang="scss"> .my-component { color: lighten(#175023, 20%); } </style>
  56. Conclusion