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