Vue.js

núria soriano   ·   blended.io

Progressive JavaScript Framework

Vue is not, and does not intend to be
the next shiny thing you should switch to ASAP” ; rather, it’s about enabling more people
to build for the web

Why should you
try it?

Approachable

Easy to start


    <div id="app">
    
      <h1>{{ message }}</h1>
    
    </div>
    
    <script>
    
      var vm = new Vue({
        data: {
          message: 'Hello World!'
        }
      }).$mount('#app')
    
    <script>

State is a plain JS object


    data: {
      message: 'Hello World!'
    }

    this.message = 'Bye World!'

State can be mutated directly


    <div id="app">
    
      <h1 v-show="visible">{{ message }}</h1>
      
      <button @click="toggle()">Toggle</button>
    
    </div>
    
    <script>
    
      var vm = new Vue({
        data: {
          message: 'Hello World!',
          visible: true
        },
        methods: {
          toggle () {
            this.visible = !this.visible
          }
        }
      }).$mount('#app')
    
    <script>

Flexible

It adapts to you

Templates vs Render Functions vs JSX

Javascript vs Typescript

Not opinionated

Extend as you need

Core: Declarative rendering & component system

Routing: vue-router

Large Scale State Management: vuex

Build system: vue-loader/vueify, vue-cli

SSR: vue-server-renderer

Performant

Light

Runtime Build 16kb min+gzip

Vue + vue-router + vuex 26kb min+gzip

Fast

Testable

Unit testing


    import Vue from 'vue'
    import Test from 'components/Test.vue'

    const vm = new Vue({
      template: '<test-component></test-component>',
      components: {
        'testComponent': Test
      }
    }).$mount()
    
    let comp = vm.$children[0]
    
    describe('Component', () => {
      it('sets the correct default data', function () {

        const defaultData = comp.dataAttribute
        expect( defaultData ).toBe('Some value')

      })
      it('has X method', function () {
        
        const methodName = comp.methodName('value')
        expect( methodName ).toBe('Some returned value')

      })
      it('renders a template', function () {
        
        const idSelector = comp.$el.getElementById('someId')
        expect( idSelector.innerText ).toBe('Some text')

      })
    })

e2e testing

nightwatch + chromedriver

Server Side Rendering

Pre-rendering

Just SEO?

Webpack + Prerender SPA Plugin


  plugins: [
    new PrerenderSpaPlugin(
      // Absolute path to compiled SPA
      Path.join(__dirname, '../dist'),
      // List of routes to prerender
      [ '/', '/about', '/contact' ]
    )
  ]

SSR

    
    const vm = new Vue({
      data: {
        msg: 'Hello world'
      },
      render (h) {
        return h('div', this.msg)
      }
    })
    
    server.get('/', (req, res) => {
      renderer.renderToString(vm, (err, html) => {
        res.send(html)
      })
    })

SSR

App

Server entry

Client entry

Server bundle

Client bundle

Context

    
    const bundleRenderer = VueServerRenderer.createBundleRenderer(serverBundle)

    server.get('*', (request, response) => {
      
      const context = { url: request.url }
      const renderStream = renderer.renderToStream(context)
 
     
      renderStream.on('data', chunk => {
        res.write(chunk)
      })
     
      renderStream.on('end', () => {
        if (context.initialState) {
          res.write(
            `<script>window.__INITIAL_STATE__=${ context.initialState }</script>`
          )
        }
        res.end('</body></html>')
      })
    
    })

   export default function (context) {

      router.push(context.url)
      const matchedComponents = router.getMatchedComponents()
    
      return Promise.all(matchedComponents.map(component => {
        if (component.preFetch) {
          return component.preFetch(store)
        }
      })).then(() => {
        context.initialState = store.state
        return app
      })

    }

Comparison

Angular


    <input [(ngModel)]="username">
    <p>Hello {{username}}!</p>
    

Vue


    <input v-model="username">
    <p>Hello {{username}}!</p>
    

    <li *ngFor="#item of list">
      {{item}}
    </li>

    <li v-for="item in list">
      {{item}}
    </li>

    <div *ngIf="errorCount > 0">
      {{errorCount}} errors detected
    </div>

    <div v-if="errorCount > 0">
      {{errorCount}} errors detected
    </div>

React

Vue


  const h = React.createElement
  const items = [1,2,3,4]

  class Iteration extends React.Component {
    render() {
      return h('ul', null, [
        arr.map(function (item) {
          return h('li', null, item)
  	})
      ]);
    }
  }

  ReactDOM.render(
    <Iteration/>, 
    document.getElementById('app')
  );

  var vm = new Vue({
    el: '#app',
    data: {
      items: [1,2,3,4]
    },
    render (h){
      return h( 'ul', 
        this.items.map(function (item) {
          return h('li', item)
  	})
      )
    }
  })

Choose what's best


  <div>
    <component-one v-if="foo === 'case1'"></component-one>
    <component-two v-if="foo === 'case2'"></component-two>
    <component-three v-if="foo === 'case3'"></component-three>
  </div>
 
  render (h){
    return h( 'div', 
      switch (foo) {
        ...
      })
    )
  }

Angular


    <hello-app></hello-app>
    
  (function() {
    var HelloApp		

    HelloApp = ng
      .Component({
	selector: 'hello-app',
	template: '<h1>{{message}}</h1>'
      })
      .Class({
	constructor: function() {
          this.message = 'Hello World'
	}
      });

    document.addEventListener('DOMContentLoaded', function() {
      ng.bootstrap(HelloApp);
    });
  }());
  
    import { Component } from '@angular/core';
    
    @Component({
      selector: 'hello-app',
      template: `<h1>{{ message }}</h1>`
    })

    export class AppComponent { name = 'Hello World'; }

React

    
    <div id="container"></div>

    var Hello = React.createClass({
      render: function() {
        return <div>{this.props.message}</div>;
      }
    });
    
    ReactDOM.render(
      <Hello message="Hello World" />,
      document.getElementById('container')
    );

Vue


    <div id="app">
      <my-component></my-component>
    </div>

    Vue.component('my-component', {
      template: '<div>{{ message }}</div>',
      data () {
        return {
          message: 'Hello World!'
        }
      }
    })

    new Vue({
      el: '#app'
    })

Vue Single File Component

Template, logic and style

Using HTML + Javascript + CSS

Or Pug, CoffeeScript, SASS…

Imported as ES2015 module

Hot-reload, scoped CSS…


    <template>
      <my-component></my-component>
    </template>
    
    <script>
      import 'myComponent' from './MyComponent'

      export default {
        name: 'app',
        components: {
          myComponent
        }
      }
    </script>

    <style lang="scss" scoped>
      div {
        color: blue
      }
    </style>

Vue & Angular

Faster to learn

Similar syntax (ng-if, v-if…)

More flexible

Vue & React

Faster to learn

Both have Virtual DOM, JSX, Render functions

Both use one-way data binding between components

State mutability

Why Vue?

Simple templating, state handling

Suited for larger apps with routing, state management & SSR

Performant & testable

Growing community

Thanks!

nuria-fl

nuria@blended.io

pincfloit

Vue.js

By nuria-fl

Vue.js

  • 1,411