A view on Vue
(last pun, I promise!)
Who am I?
- Vue.js core team
- Web UI/visualization developer and consultant
@chrisvfritz (slack.lansing.codes)
@chrisvfritz
@chrisvfritz
What are components?
HTML
- todo-list.html
- _todo.html
- _button.html
CSS
- todo-list.css
JS
- todo-list.js
TodoList
HTML
CSS
JS
Todo
HTML
CSS
JS
Button
HTML
CSS
JS
Components are the future
...but which component system?
"My biggest frustration is the constant migration from tool to tool or framework to framework. Never any time to master one before something better comes along."
The elephant in the room...
What would it take?
- Be productive almost immediately
- Simple (in practice!) component model
- Fast, easy-to-optimize rendering
- Must scale well to large apps
- Top-class dev workflow
- Stable and rich ecosystem
Coming from React, this is what I needed
Getting started
- Documentation
- Learning curve
- Support
Documentation
Learning curve
<div id="app">
<input v-model="greeting">
<p>{{ greeting }} World</p>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
el: '#app',
data: {
greeting: 'Hello'
}
})
</script>
Hello world!
Angular
Learning curve
<script src="https://unpkg.com/angular/angular.js"></script>
<script>
angular.module('HelloWorldApp', [])
.controller('HelloWorldController', function ($scope) {
$scope.greeting = 'Hello'
})
</script>
<div ng-app="HelloWorldApp">
<div ng-controller="HelloWorldController">
<input ng-model="greeting">
<p>{{ greeting }} world</p>
</div>
</div>
and with Angular 1...
Learning curve
<div id="app">
<input v-model="newTodoText" @keydown.enter="addTodo">
<ul>
<li v-for="(todo, index) in todos">
{{ todo.text }}
<button @click="removeTodo(index)">X</button>
</li>
</ul>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
new Vue({
el: '#app',
data: {
newTodoText: '',
todos: []
},
methods: {
addTodo: function () {
this.todos.push({ text: this.newTodoText })
this.newTodoText = ''
},
removeTodo: function (index) {
this.todos.splice(index, 1)
}
}
})
</script>
Simple todo app
Angular
Learning curve
<script src="https://unpkg.com/angular/angular.js"></script>
<script>
angular.module('TodoApp', [])
.controller('TodoController', function ($scope) {
$scope.newTodoText = ''
$scope.todos = []
$scope.addTodo = function () {
$scope.todos.push({ text: $scope.newTodoText })
$scope.newTodoText = ''
}
$scope.removeTodo = function (index) {
$scope.todos.splice(index, 1)
}
})
</script>
<div ng-app="TodoApp">
<div ng-controller="TodoController">
<input ng-model="newTodoText" ng-keydown="$event.which === 13 && addTodo()">
<ul>
<li ng-repeat="todo in todos">
{{ todo.text }}
<button ng-click="removeTodo($index)">X</button>
</li>
</ul>
</div>
</div>
and with Angular 1...
Learning curve
<div id="app">
It will have been 2 minutes since I loaded this page in
<auto-counter
:initial-value="120"
:increment-by="-1"
:stop-at="0"
></auto-counter>
seconds.
</div>
<script src="https://unpkg.com/vue"></script>
<script>
Vue.component('auto-counter', {
template: '<span>{{ number }}</span>',
props: {
initialValue: {
type: Number,
default: 0
},
incrementBy: {
type: Number,
default: 1
},
interval: {
type: Number,
default: 1000
},
stopAt: {
type: Number
}
},
data: function () {
return {
number: this.initialValue
}
},
created: function () {
var vm = this
vm.counter = setInterval(function () {
vm.number += vm.incrementBy
if (this.stopAt === vm.number) {
clearInterval(vm.counter)
}
}, vm.interval)
},
beforeDestroy: function () {
clearInterval(this.counter)
}
})
new Vue({ el: '#app' })
</script>
Reusable components
Angular
Learning curve
<script src="https://unpkg.com/angular/angular.js"></script>
<script>
angular.module('App', [])
.component('autoCounter', {
template: '<span>{{ $ctrl.number }}</span>',
controller: function ($scope) {
var vm = this
vm.$onInit = function () {
vm.number = vm.initialValue || 0
vm.incrementBy = vm.incrementBy || 1
vm.interval = vm.interval || 1000
vm.counter = setInterval(function () {
$scope.$apply(function () {
vm.number += vm.incrementBy
if (vm.stopAt === vm.number) {
clearInterval(vm.counter)
}
})
}, vm.interval)
}
vm.$onDestroy = function () {
clearInterval(vm.counter)
}
},
bindings: {
initialValue: '<',
incrementBy: '<',
interval: '<',
stopAt: '<'
}
})
</script>
<div ng-app="App">
It will have been 2 minutes since I loaded this page in
<auto-counter
initial-value="120"
increment-by="-1"
stop-at="0"
></auto-counter>
seconds.
</div>
and with Angular 1...
Support
- GitHub
- Discourse forum
- Gitter chat
Single-File Components
Build on web standards, don't reinvent them
<template>
<button :class="'btn btn-' + kind">
<slot></slot>
</button>
</template>
<script>
export default {
props: {
kind: {
validator (value) {
return ['primary', 'warning'].indexOf(value) !== -1
},
required: true
}
}
}
</script>
<style lang="scss" scoped>
$text-color: #fff;
$primary-bg-color: #0074d9;
$warning-bg-color: #d5a13c;
.btn {
color: $text-color;
&.btn-primary {
background: $primary-bg-color;
&:hover {
background: lighten($primary-bg-color, 20%);
}
}
&.btn-warning {
background: $warning-bg-color;
&:hover {
background: lighten($warning-bg-color, 20%);
}
}
}
</style>
Integrating 3rd Party Libs
<template>
<textarea :value="markdown" @input="updateMarkdown"></textarea>
<div v-html="preview"/>
</template>
<script>
import debounce from 'lodash/debounce'
import compileMarkdown from 'marked'
export default {
el: '#editor',
data: {
markdown: '# hello'
},
computed: {
preview: function () {
return compileMarkdown(this.markdown)
}
},
methods: {
updateMarkdown: debounce(function (event) {
this.markdown = event.target.value
}, 300)
}
})
</script>
Markdown Editor
Integrating 3rd Party Libs
Visualization with D3
I need to create a page that displays the latest activity from the users, so I just need to get the data from the REST endpoint and display it in some sort of filterable table, and update it if anything changes in the server.
Integrating 3rd Party Libs
REST
Scaling Up
Dev Workflow
In-browser devtools
Dev Workflow
With time travel!
Dev Workflow
Hot module reloading
Ecosystem
Is anyone actually using it in production?
Ecosystem
Official support for practically required libs (like for routing and state management)
github.com/vuejs/vue-router
github.com/vuejs/vuex
github.com/vuejs/vue-cli
github.com/vuejs/vue-rx
...
Ajax
Routing
Flux State
CLI Generator
Devtools
Observables
...
Plumbing
@chrisvfritz (slack.lansing.codes)
@chrisvfritz
@chrisvfritz
slides.com/chrisfritz/vue-mmcfug
Intro to Vue.js
By Chris Fritz
Intro to Vue.js
- 1,885