VueJS

The Progressive JavaScript Framework

Meir Kriheli / @mkriheli

PyWeb-IL 69, Oct 2, 2017

Short History

  • Created by Evan You
  • Worked at Google
  • Liked some concepts in Angular
  • Not the complexity
"I figured, what if I could just extract the part that I really liked about Angular and build something really lightweight without all the extra concepts involved?"
  • First released February 2014
  • Made a splash at Reddit, HN, etc.
  • Successful in China
  • Version 2.0 Released at April 2016
  • Made popular by Laravel community
  • Adopted by quote few project, e.g. GitLab
  • Successful open source product
  • Stars, community, closed bugs
  • Evan is self sustained via Patreon

Progressive?

  • Less opinionated
  • Incrementally adoptable architecture
  • Can start simple - enhance a page
  • e.g.: Embed into Django or Jinja template
  • Up to full blown SPA

Core

  • Performance and size
  • Focus on making UI devel more approachable
  • Learning from other frameworks pros and cons
  • Declarative rendering
  • Component Composition

Advanced Features

Officially maintained!

  • CLI starter (webpack, browserify, ES2015, scss)
  • Single file components
  • Routing
  • State management

Good, easy to follow documentation

Basics

Basic Vue App


<script src="https://unpkg.com/vue"></script>

<div id="app">
  <p>{{ message }}</p>
</div>

<script>
  new Vue({
    el: '#app', // <- Element to mount the app on
    data: {     // <- Reactive data
      message: 'Hello Vue.js!'
    }
  })
</script>
            

Bound HTML attributes

For reactive HTML attributes use v-bind


<img src="{{ imgURL }}"> <-- Won't work -->
<img v-bind:src="imgURL"> <-- That's it -->
            
or shorthand syntax:

<img :src="imgURL"> <-- Nice -->
            

Events

Use v-on


<button v-on:click="message = 'yo'">Change message</button>
            
or shorthand syntax:

<button @click="message = 'yo'">Change message</button>
            

Event Modifiers

Control DOM events without writing code. Some modifiers from the docs:


<!-- the click event's propagation will be stopped -->
<a v-on:click.stop="doThis"></a>

<!-- the submit event will no longer reload the page -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- modifiers can be chained -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- just the modifier -->
<form v-on:submit.prevent></form>
            

For key and mouse events too

See the docs


<!-- only call vm.submit() when the keyCode is 13 -->
<input v-on:keyup.enter="submit">

<!-- Alt + C -->
<input @keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div @click.ctrl="doSomething">Do something</div>
            

Methods

<div id="app">
  <p>{{ message }}</p>
  <button @click="changeMessage"></button>
</div>

<script>
  new Vue({
    el: '#app', // <- Element to mount the app on
    data: {     // <- Reactive data
      message: 'Hello Vue.js!'
    },
    methods: {
      changeMessage: function() {
        this.message = 'Yo';
      }
    }
  })
</script>

Proxying

Note the usage of this and the way the template uses data and methods without their keys.

Vue proxies them for us, some with getter/setters to track data changes. It also handles binding this.

Proxying Caveats

Sometimes Vue can't detect property changes, e.g.:

arr[10] = 12;

or when adding keys dynamically to data.

In those case use Vue.set:

Vue.set(arr, 10, 12);

See also Reactivity in Depth.

Computed properties

<div id="example">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // a computed getter
    reversedMessage: function () {
      // `this` points to the vm instance
      return this.message.split('').reverse().join('')
    }
  }
})

Unlike methods, computed properties are cached based on their dependencies.

Hammer Fiddle time

Enough theory, let's have some fun with JSFiddle.

Control Flow Directives

Conditional

  • v-if
  • v-else

Add/Remove items from DOM:


<div v-if="Math.random() > 0.5">
  Now you see me
</div>
<div v-else>
  Now you don't
</div>
            

v-else-if

Since 2.1.0


<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>
            

v-show

Always rendered in DOM, toggles display style.

List rendering: v-for

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>

<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>

<div v-for="(value, key) in object">
  {{ key }}: {{ value }}
</div>

Form Inputs

Two way data binding with v-model:


<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
          

Modifiers: .lazy, .number, .trim.

Let's look at the docs.

Components

Pretty much like the Vue instance.

Vue.component('panel', {  // registered globally
  props: ['message'], // declare the props the component accepts
  data: function() { // Must, otherwise will be shared by instances
    return {
      counter: 0
    }
  },
  template: '<div class="panel">{{ message }}</div>'
});

<panel message="hello!"></panel>
            

Data Flow

  • Top-to-Bottom (parent to child)
  • Use this.$emit() to parent changes.
  • Use a Vue() instance as event bus for cross component notifications.

Slots

Follows HTML template standards.

Like Angular 1's transclude.

<-- component template -->
<div>
  <h2>I'm the child title</h2>
  <slot>
    This will only be displayed if there is no content
  </slot>
</div>

<!-- parent template -->
<div>
  <h1>I'm the parent title</h1>
  <my-component>
    <p>This is some original content</p>
    <p>Will be displayed inside the slot</p>
  </my-component>
</div>

CLI detour

Play with build tools, single file components, browser dev tools, and ES2015 goodness.


$ # install vue-cli
$ npm install --global vue-cli
$ # create a new project using the "webpack" template
$ vue init webpack my-project
# install dependencies and go!
$ cd my-project
$ npm install
$ npm run dev
            

Play time

Rich Ecosystem

  • Quasar Framework - Responsive, PWAs, hybrid mobile apps
  • Weex - Native mobile apps
  • Buefy - Lightweight UI components
  • NUXT.js - Server side rendering and static generation.

Awesome Vue.js - A curated list of Vue.js related things. .

I know kung fu

Currently @Vast Data

We're hiring: Python, C++, QA and Automation

 

Thank you