WarsawJS #39 Vue.js - mix of Angular and React

We talk about JavaScript. Each month in Warsaw, Poland.

Speaker

Jakub Skałecki @jskalc

Vue.js - great mix of React and Angular [PL]

2017-10-08

WHAMI

React + Angular =

Vue logo

My experience with Angular

My experience with React

Meme

I had to prepare a simple dashboard

Quite standard requirements: API calls, pagination, filters

I wanted to do it in the most simple way (no jQuery), and learn something

Internal project, should just work

I've heard Vue is gaining traction, why not to try it?

Vue - what they say

Learning from the mistakes and successes of React & Angular

HTML is HTML, JS is JS, CSS is CSS

Progressive web framework

Never stands in your way

Right amount of Magic

First impressions?

Documentation is great!

Syntax is simple!

It just works!

Outcome

Frontend part implemented using Vue and Bulma in just one HTML file

Done in 6h since a first look to the documentation

Very clean, readable code

Final impression - it was so simple! Let's try something bigger

Examples

Hello world

            
                <script src="https://unpkg.com/vue"></script>
                <div id="app">
                    {{ message }}
                </div>
            
        
            
                var app = new Vue({
                  el: '#app',
                  data: { message: 'Hello Vue!' }
                })
            
        

Hello world output

{{ message }}

Methods and handlers

            
                <div id="app">
                    Hello {{ name }}!
                    <button @click="modify">Where I am?</button>
                </div>
            
        

Methods and handlers

            
                new Vue({
                    el: "#app",
                    data: { name: 'Vue' },
                    methods: {
                        modify: function() {
                            this.name = 'WarsawJS'
                        }
                    }
                })
            
        

Methods and handlers

Hello {{ name }}!

v-model and v-if

            
                <div id="app">
                    <div v-if="name">
                        Hello {{ name }}!
                    </div>
                    <div v-else>
                        Who are you?
                    </div>
                    <input v-model="name" placeholder="name">
                </div>
            
        

v-model and v-if

            
                <input v-model="name">
            
        

is the same as

            
                <input v-on:input="name = $event.target.value"
                       v-bind:value="name">
            
        

v-model and v-if

is the same as

            
                <input @input="name = $event.target.value"
                       :value="name">
            
        

v-model and v-if

Hello {{ name }}!
Who are you?

v-for, computed data and filter

            
                data: {
                  entries: []
                },
                methods: {
                  addEntry: function () {
                    this.entries.push(this.entry)
                    this.entry = '';
                  }
                }
            
        

v-for, computed data and filter

            
                computed: {
                  filteredEntries: function () {
                    var bad = ['bad', 'weak', 'boring']
                    return this.entries.filter(function(entry) {
                      return bad.indexOf(entry.toLowerCase()) === -1
                    })
                  }
                }
            
        

v-for, computed data and filter

            
                filters: {
                  shout: function(value) {
                    return 'They said "' + value + '"!';
                  }
                }
            
        

v-for, computed data and filter

            
                <input v-model="entry" @keyup.enter="addEntry">
                <div v-if="filteredEntries">
                    <ul>
                        <li v-for="e in filteredEntries">
                            {{ e }}
                        </li>
                    </ul>
                </div>
            
        

v-for, computed data and filter

Describe WarsawJS
{{ e | shout }}

watch - api call example

            
                data: {
                  query: '',
                  searching: false,
                  people: []
                },
            
        

watch - api call example

            
              search: function (query) {
                this.searching = true;
                axios.get('https://swapi.co/api/people/', {params: {search: query}})
                  .then(function(response) {
                    that.people = response.data.results.map(...);
                    that.searching = false;
                  })
              }
            
        

watch - api call example

            
              watch: {
                query: function(value) {
                  this.search(value)
                })
              }
            
        

watch - api call example

            
              watch: {
                query: _.debounce(function(value) {
                  this.search(value)
                }, 500)
              }
            
        

watch - api call example

            
                <input v-model="query" placeholder="Search...">
                <div v-if="searching">Searching...</div>
                <div v-else-if="people.length > 0">
                    <div v-for="person in people">
                        {{ person }}
                    </div>
                </div>
                <div v-else>No records found</div>
            
        

watch - api call example

Searching...
{{ person }}
No records found

Components - creation

            
                Vue.component('vue-data', {
                  props: ['data'],
                  template: '<pre class="data">' +
                            '  $data: {{ JSON.stringify(data) }}' +
                            '</pre>'
                })
            
        

Components - usage

            
                <vue-data :data="$data"></vue-data>
            
        

There are also "slots"

            
                <template><slot name="content">Placeholder</slot></template>
                <component>
                    <h1 slot="content">Important content</h1>
                </component>
            
        

Single File Components

Single File Components example

            
                <template>
                    <div class="hello">{{ msg }}</div>
                </template>
                <script>
                    export default {
                        data: () => ({ msg: "Hello, components!" })
                    }
                </script>
            
        

Single File Components example

            
                <style language="scss" scoped>
                    div {
                        color: red;
                        .hello {
                            font-size: 2em;
                        }
                    }
                </style>
            
        

Single File Components usage

            
                <template>
                    <component>{{ msg }}</component>
                </template>
                <script>
                    import Component from './component.vue'
                    export default {
                        components: { Component }
                    }
                </script>
            
        

Parent - child communication

React - usually passing function as a prop

Angular - $emit() + $on() with scopes

Vue - $emit() + v-on:event="", only direct children

Parent - child communication example

Child
            
                <button @click="$emit('clicked')">Submit</button>
            
        
Parent
            
                <child @clicked="alert('yay')"></child>
            
        

Parent - child communication example

Child
            
                <button @click="$emit('clicked', 'Hello')">Submit</button>
            
        
Parent
            
                    <child @clicked="value => alert(value)"></child>
            
        

Reactivity

How Vue works under the hood?

Taken from React

Utilizes a virtual DOM

Provides reactive and composable view components

Lightweight, no batteries included

Taken from Angular

Beautiful, readable HTML additions

Ecosystem

Ecosystem

Modern features

Rising stars 2016 winner

Github stars

  1. React - 80,432
  2. Vue - 72,965
  3. AngularJS - 57,466
  4. Angular - 29,731

Common objections

One man project

It (Vue.js) has also grown from “yet another side project” into an ecosystem with over 300 contributors across the Vue.js organization,and maintained by a core team of over 20 active members across the globe

Evan You, the creator of Vue.js

Scalability

Vue is built on the component-based model for UI development which is a proven pattern shared among all major frameworks, with solid official solutions for SPA routing and large-scale state management. It is designed for approachability, but is also designed with scale in mind.

Evan You, the creator of Vue.js

Never heard of a big company using Vue

VueJS workshops 19.11.2017

Thank you!

Speaker

Jakub Skałecki

@jskalc

See you next month at WarsawJS