Copyright (c) 2017 Euricom nv. <style type="text/css"> /* .reveal p { text-align: left; } .reveal ul { display: block; } .reveal ol { display: block; } */ </style>
Easy does it.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My First Vue</title>
</head>
<body>
<input type="text" id="input">
<script>
let data = {
message: 'Hello World'
}
document.querySelector('#input').value = data.message
</script>
</body>
</html>
Launch your webpage by using serve
or live-server
$ live-server
Serving "/Users/me/git/vue" at http://127.0.0.1:8080
GET /favicon.ico 404 2.100 ms - 24
Add VueJS
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
Replace the script
<script>
new Vue({
el: '#root',
data() {
return {
message: 'Hello World'
}
}
})
</script>
Add a template binding
<div id="root">
<input type="text" id="input" v-model="message">
<p>The Value of the input is: {{message}}</p>
</div>
This gives us 2-way binding with the v-model
directive and output binding with {{...}}
.
Open devtools and notice the following message:
Get it on the Chrome Web Store
You can inspect the Vue components and interact with them. See also the $vm0 (and others) variabled to inpect or change via the console.
Single root of truth: the view, the data, the console, the devtools.
Let move the javascript to separate file: main.js
// eslint-disable-next-line
new Vue({
el: '#root',
data: {
message: 'Hello World',
},
})
And reference the main.js
<body>
<div id="root">
<input type="text" id="input" v-model="message">
<p>The Value of the input is: {{message}}</p>
</div>
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="./main.js"></script>
</body>
Connect your model to the view
Simple binding (mustaches)
<p>The Value of the input is:
<span>{{message}}</span>
</p>
v-text
directive
<p>The Value of the input is:
<span v-text="name"></span>
</p>
v-html
directive
<div v-html="rawHtml"></div>
Using javascript expressions
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<span>new Date()</span>
<ul>
<li v-for="item in tasks" v-if="item.completed">
{{item.description}}
</li>
</ul>
vs
<span>{{now}}</span>
<ul>
<li v-for="item in incompleteTasks">
{{item.description}}
</li>
</ul>
data() {
...
},
computed: {
now() {
return new Date()
}
incompleteTasks() {
return this.tasks.filter(task => !task.completed)
}
}
Simple text formatting
{{ message | toUpperCase }}
<div v-text="date | formatDate"></div>
new Vue({
// ...
filters: {
toUpperCase: function (value) {
if (!value) return ''
return value.toString().toUpperCase()
}
}
})
Can take arguments
{{ message | filterA('arg1', arg2) }}
Can be chained
{{ message | filter1 | filter2 }}
VueJS 2.0 doesn't has standard filters: 3th party package
Create a list
data() {
return {
message: 'Hello World',
names: ['Joe', 'Mary', 'Jane', 'Jack'],
}
},
Use the v-for
directive
<div id="root">
...
<ul>
<li v-for="name in names">{{name}}</li>
</ul>
</div>
You can inpect the array in the devTools
v-if
and v-else
directive
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
v-show
directive
<h1 v-show="ok">Hello!</h1>
v-show
is using CSS to show/hide content,v-if
removes the content from the dom.
Set button title
<button title="hit me">Add</button>
Set button title at runtime: v-bind
directive
data() {
return {
names: ['Joe', 'Mary', 'Jane', 'Jack'],
buttonTitle: 'Click me to add a name',
}
}
<button v-bind:title="title">Add</button>
Or shorthand syntax (mostly used)
<button :title="title">Add</button>
Use it for classes
<button :class="buttonClass">Add</button>
data() {
return {
buttonClass: 'active'
}
}
Conditional Class binding
<style>
.is-loading { background: red; }
</style>
<button :class="{ 'is-loading': isLoading }">
data() {
return {
...
isLoading: false,
}
}
React to user input
<!-- `greet` is the name of a method defined below -->
<button v-on:click="greet($event)">ClickMe</button>
Or shorthand syntax (mostly used)
<button @click="greet($event)">ClickMe</button>
Event Handler
var example2 = new Vue({
...
data() {
return {
name: 'Vue.js'
},
},
// define methods under the `methods` object
methods: {
greet: function (event) {
// `this` inside methods points to the Vue instance
alert('Hello ' + this.name + '!')
// `event` is the native DOM event
if (event) {
alert(event.target.tagName)
}
}
}
})
It is a very common need to call event.preventDefault()
or event.stopPropagation()
inside event handlers.
methods: {
greet: function (event) {
event.preventDefault()
...
}
}
Simplified
<a @click.prevent="greet($event)"></a>
Key modifiers:
<!-- only call vm.submit() when the keyCode is 13 -->
<input v-on:keyup.13="submit">
More: https://vuejs.org/v2/guide/events.html#Event-Modifiers
Use a button to toggle (hide/show) a paragraph of text
- Look for 3 solutions
The power of VueJS
Re-usable UI components: like extending your html
// Extend Vue to get a reusable constructor
var MyComponent = Vue.extend({
template: '<div>A custom component!<div>'
})
// Register the constructor with id: my-component
Vue.component('my-component', MyComponent)
Simplified
Vue.component('my-component', {
template: 'A custom component!'
})
And use
<div id="root">
<my-component></my-component>
</div>
Its like React Children & Angular transclude, its passes all the inner content (like inner html) to the template.
var MyComponent = Vue.extend({
template: `
<div>
<h1>{{title}}</h1>
<slot></slot>
</div>
`,
data() {
return {
title: 'My Component'
}
}
})
And use it
<div id="root">
<my-component>
<span> Add some text here </span>
</my-component>
</div>
I want to set my title on the component
<div id="root">
<my-component title="My Component Title" sub-title="bla bla bla">
<span> Add some text here </span>
</my-component>
</div>
In code
var MyComponent = Vue.extend({
props: [
'title',
'sub-message'
],
template: `
<div>
<h1>{{title}}</h1>
<h3>{{subTitle}}</h3>
<slot></slot>
</div>
`
})
More https://vuejs.org/v2/guide/components.html#Prop-Validation
You can use v-bind
(or use : syntax) on custom properties
<my-component :title="title" :sub-title="subTitle">
<span> Add some text here </span>
</my-component>
var MyComponent = Vue.extend({
template: `
<div>
<h1>My Super Button</h1>
<button @click="onClick()">Finish</button>
</div>
`,
methods: {
onClick() {
this.$emit('handled', { id: 123 })
}
}
})
<div id="root">
<my-component @handled="onHandled($event)">
</my-component>
</div>
created() {
// Instance is created
}
mounted() {
// vm.$el is created (html in doc)
},
updated() {
// Called after a data change
},
destroyed() {
// Called after a Vue instance has been destroyed
}
More: https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram
Create dismissible bootstrap alert
- Use bootstrap styling: http://getbootstrap.com/components/#alerts-dismissible
- Create VueJS component
<!-- default alert: warning -->
<alert>
Almost out of stock
</alert>
<!-- custom alert with event -->
<alert type="alert" @closed="onClosed()">
<strong>Alert!</strong> We have a problem.
</alert>
- Don't use jqeury or the bootstrap js library
- Log a message to the console if the dialog is closed
Get your user input
<!-- text -->
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<!-- checkbox -->
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
<!-- radio -->
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: {{ picked }}</span>
<!-- select -->
<select v-model="selected">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
Form with bootstrap styling
<form @submit.prevent="addUser">
<div class="form-group">
<label for="firstName">First Name:</label>
<input type="text" class="form-control"
id="firstName" v-model="user.firstName">
</div>
... other
<button class="btn btn-defaut" @click.prevent="$router.go(-1)">Back</button>
<button type="submit" class="btn btn-default">Submit</button>
</form>
Communicating between components
Communicating between components with direct access
this.$root // app root
this.$parent // parent component
this.$children // children components
Warning: Only use them when you know why you should.
In simple scenarios, you can use an empty Vue instance as a central event bus.
var bus = new Vue();
In a component
bus.$emit('myEvent', 123) // same instance
And listen for it
but.$on('myEvent', (value) => {
...
})
class EventAggregator {
constructor() {
this.vue = new Vue()
}
fire(event, data = null) {
this.vue.$emit(event, data)
}
listen(event, callback) {
this.vue.$on(event, callback)
}
}
export const eventAggregator = new EventAggregator()
Usage
import { eventAggregator } from 'eventAggregator'
// component A
methods: {
onClick() {
eventAggregator.fire('myEvent', { ... })
}
}
// component B
created() {
eventAggregator.listen('myEvent', (value) => {
console.log('handle it: ', value)
})
}
Extend the behavior of existing elements
Like the build in directives v-text
, v-show
but build yourself.
Vue.directive('focus', {
// When the bound element is inserted into the DOM...
inserted: function (el) {
// Focus the element
el.focus()
}
})
And use it
<input v-focus>
More: https://vuejs.org/v2/guide/custom-directive.html#Hook-Functions
- We have the following translation service
class TranslationService {
constructor () {
this.translations = {
'Welcome to Vue': {
nl: 'Welkom in Vue',
},
}
this.language = 'nl'
}
getTranslation (message) {
const trans = this.translations[message][this.language]
return trans || message
}
}
- Create a translate directive based on a selected language
<button @click="setLang('nl)">NL</button>
<button @click="setLang('en)">EN</button>
<h1 translate>Welcome to Vue</h1>
output:
<h1>Welkom in Vue</h1>
- use vm.$forceUpdate() to re-render the view on language change
See './exercise/vuejs' for a simple solution
See https://github.com/javisperez/vuetranslate for a solution.
They are more common then you think
Angular2 VueJS
--------------- ----------------
[attr]="value" :attr="value" or v-bind:attr="value"
(click)="onClick()" @click="onClick" or v-on:click="onClick"
{{name}} {{name}}
[innerHtml]="rawHtml" v-html="rawHtml"
*ngFor="item of items" v-for="item in items"
*ngIf="condition" v-if="condition"
[hidden]="condition" v-show="condition"
{{ message | uppercase }} {{ message | uppercase}}
{{ msg | upper:5 }} {{ msg | upper 5}}
ngModel="name" v-model="name"
// Angular2
@Component({
selector: 'counter',
template: `<div>{{sample}}</div>`,
})
export class CounterComponent {
@Input() name
constructor() {
this.name = 'sample'
}
ngOnInit() {
}
onCustomHandle() {
}
}
// VueJS
Vue.component('counter', {
props: ['name']
template: `<div>{{sample}}</div>`,
methods: {
onCustomHandle() {
}
},
data: {
return {
name: 'sample',
}
}
created() {
},
});
Angular2
<myComponent (myEvent)="onEvent($event)">
@Ouput() myEvent = new EventEmitter()
myEvent.emit(value)
VueJS
<myComponent @myEvent="onEvent($event)">
this.$emit('myEvent', value)
Learn
General
Advanced
Tools/Libraries
Book