KEMBAR78
Level up apps and websites with vue.js
LEVEL-UP APPS & WEBSITES
WITH VUE.JS
Level-up
apps & websites
with vue.js
twitter:
@loregirardi
github:
@liqueflies
hey folks
i am
lorenzo girardi
twitter:
@loregirardi
github:
@liqueflies
hello commit
i am a
front-end dev
and a passionate
musician
twitter:
@loregirardi
github:
@liqueflies
digital company with strong focus on
strategy and technology
website:
https://www.develondigital.com/
international group
+15 years
+55 people
+5 departments
website:
https://www.develondigital.com/
thanks for having us!
is it easy
to build websites?
twitter:
@loregirardi
github:
@liqueflies
Our team was searching for a tool
with data driven development in mind...
...and a lean learning curve because
we had to be production-ready ASAP.
twitter:
@loregirardi
github:
@liqueflies
+ =
website:
https://vuejs.org/
/vjuː/
website:
https://vuejs.org/
website:
https://vuejs.org/
progressive
framework
evan you
vue vue-router vuex vue-cli
website:
https://vuejs.org/
numbers
> 82k stars (87k react, 32k angular)
~ 4000 packages depends on it
> 1.000.000 download last month
$ 11.567 per month by 204 patreons
2 vueconf in 2018 (amsterdam, new orleans)
basic
concepts
website:
https://vuejs.org/
website:
https://vuejs.org/
website:
https://vuejs.org/
<script src="vue.js"></script>
<div id="app">
<p>{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello commit people!'
}
})
</script>
https://vuejs.org/ hello world
<script src="vue.js"></script>
<div id="app">
<p>{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello commit people!'
}
})
</script>
https://vuejs.org/ hello world
<script src="vue.js"></script>
<div id="app">
<p>{{ message }}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello commit people!'
}
})
</script>
https://vuejs.org/ hello world
<script src="vue.js"></script>
<div id="app">
<img v-bind:src="src" :alt="alt" />
</div>
<script>
new Vue({
el: '#app',
data: {
src: 'https://picsum.photos/200/300',
alt: 'A random pic from the web.'
}
})
</script>
https://vuejs.org/v2/guide/syntax.html attributes binding
<script src="vue.js"></script>
<div id="app">
<img v-bind:src="src" :alt="alt" />
</div>
<script>
new Vue({
el: '#app',
data: {
src: 'https://picsum.photos/200/300',
alt: 'A random pic from the web.'
}
})
</script>
https://vuejs.org/v2/guide/syntax.html attributes binding
<script src="vue.js"></script>
<div id="app">
<img v-bind:src="src" :alt="alt" />
</div>
<script>
new Vue({
el: '#app',
data: {
src: 'https://picsum.photos/200/300',
alt: 'A random pic from the web.'
}
})
</script>
https://vuejs.org/v2/guide/syntax.html attributes binding
<script src="vue.js"></script>
<div id="app">
<p v-if="visible"> I’m not rendered </p>
<p v-show="visible"> I’m hidden [i.e. display: none] </p>
</div>
<script>
new Vue({
el: '#app',
data: {
visible: false
}
})
</script>
https://vuejs.org/v2/guide/syntax.html conditional render/display
<script src="vue.js"></script>
<div id="app">
<p v-if="visible"> I’m not rendered </p>
<p v-show="visible"> I’m hidden [i.e. display: none] </p>
</div>
<script>
new Vue({
el: '#app',
data: {
visible: false
}
})
</script>
https://vuejs.org/v2/guide/syntax.html conditional render/display
<script src="vue.js"></script>
<ul id="app">
<li v-for="todo in todos" :key="todo">
{{ todo }}
</li>
</ul>
<script>
new Vue({
el: '#app',
data: {
todos: ['eat', 'sleep', 'repeat']
}
})
</script>
https://vuejs.org/v2/guide/syntax.html loop through elements
<script src="vue.js"></script>
<ul id="app">
<li v-for="todo in todos" :key="todo">
{{ todo }}
</li>
</ul>
<script>
new Vue({
el: '#app',
data: {
todos: ['eat', 'sleep', 'repeat']
}
})
</script>
https://vuejs.org/v2/guide/syntax.html loop through elements
<script src="vue.js"></script>
<div id="app">
<p> {{ message }} </p>
<button @click="message = ''"> Reset </button>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Please, reset me!'
}
})
</script>
https://vuejs.org/v2/guide/syntax.html handle user input
<script src="vue.js"></script>
<div id="app">
<p> {{ message }} </p>
<button @click="message = ''"> Reset </button>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Please, reset me!'
}
})
</script>
https://vuejs.org/v2/guide/syntax.html handle user input
<script src="vue.js"></script>
<div id="app">
<p> you typed: {{ message }} </p>
<input v-model="message" placeholder="start typing..." />
</div>
<script>
new Vue({
el: '#app',
data: {
message: ''
}
})
</script>
https://vuejs.org/v2/guide/syntax.html handle user input
<script src="vue.js"></script>
<div id="app">
<p> you typed: {{ message }} </p>
<input v-model="message" placeholder="start typing..." />
</div>
<script>
new Vue({
el: '#app',
data: {
message: ''
}
})
</script>
https://vuejs.org/v2/guide/syntax.html handle user input
syntax
Focusing
- semantic code
- easy to read
- easy to maintain
- easy to share code
in teams.
setting data
Focusing
set data in vue.js is not async.
is the same as you do in javascript.
this.setState({ counter: this.state.counter++ })
this.setState({ counter: this.state.counter++ })
have you ever tried?
computed
and methods
website:
https://vuejs.org/
<ul id="app">
<p> The higher number is: {{ higherNumber }} </p>
</ul>
new Vue({
el: '#app',
data: {
numbers: [100, 2, 345, 42, 56]
},
computed: {
higherNumber: function () {
return Math.max(...this.numbers)
}
}
})
https://vuejs.org/v2/guide/syntax.html computed
<ul id="app">
<p> The higher number is: {{ higherNumber }} </p>
</ul>
new Vue({
el: '#app',
data: {
numbers: [100, 2, 345, 42, 56]
},
computed: {
higherNumber: function () {
return Math.max(...this.numbers)
}
}
})
https://vuejs.org/v2/guide/syntax.html computed
<ul id="app">
<p> The higher number is: {{ higherNumber }} </p>
</ul>
new Vue({
el: '#app',
data: {
numbers: [100, 2, 345, 42, 56]
},
computed: {
higherNumber: function () {
return Math.max(...this.numbers)
}
}
})
https://vuejs.org/v2/guide/syntax.html computed
<div id="app">
<p v-show="visible"> I am visible. </p>
<button @click="toggleVisibility"> toggle visibility </button>
</div>
new Vue({
el: '#app',
data: {
visible: false
},
methods: {
toggleVisibility: function (event) {
this.visible = !this.visible
}
}
})
https://vuejs.org/v2/guide/syntax.html methods
<div id="app">
<p v-show="visible"> I am visible. </p>
<button @click="toggleVisibility"> toggle visibility </button>
</div>
new Vue({
el: '#app',
data: {
visible: false
},
methods: {
toggleVisibility: function (event) {
this.visible = !this.visible
}
}
})
https://vuejs.org/v2/guide/syntax.html methods
computed
Focusing
- runs when its
own dependencies
updates
- called and used
as data properties
- is cached
methods
Focusing
- runs when
you need to use it
- called as a
function in event
bindings
- is not cached
summary
Focusing
- no this hell (context is auto-binded)
- no async data beginner failures
- no shouldUpdate worries
- no build steps needed
content
management with
components
website:
https://vuejs.org/v2/components.html
<the-header />
<aside>
<main-menu />
</aside>
<main>
<blog-posts />
</main>
<the-footer />
https://vuejs.org/v2/components.htm
l
components
tree structure
component
Focusing
- encapsulation of elements
that can be accessed
through one single element.
- encapsulation of logic,
but in different instances
- encapsulation of style (module, scoped)
// ...in root component
<div id="app">
<card-item />
</div>
Vue.component('card-item', {
template: '...',
data: function () {
return {
...
}
}
})
https://vuejs.org/v2/components.html
// ...in root component
<div id="app">
<card-item />
</div>
<script>
Vue.component('card-item', {
template: '...',
data: function () {
return { ... }
}
})
</script>
https://vuejs.org/v2/components.html
<script type="text/x-template" id="card-template">
<article>
<h2> {{ title }} </h2>
<img :src="img" :alt="title" />
</article>
</script>
Vue.component('card-item', {
template: '#card-template',
data: function () {
return {
title: 'A card title'
img: 'https://picsum.photos/200/300'
}
}
})
https://vuejs.org/v2/components.html
<script type="text/x-template" id="card-template">
<article>
<h2> {{ title }} </h2>
<img :src="img" :alt="title" />
</article>
</script>
Vue.component('card-item', {
template: '#card-template',
data: function () {
return {
title: 'A card title'
img: 'https://picsum.photos/200/300'
}
}
})
https://vuejs.org/v2/components.html
{
...
data () {
return {
title: 'A card title'
img: 'https://picsum.photos/200/300'
}
}
...
}
https://vuejs.org/v2/components.html
data is a function
now we can encapsulate logic
and style in a component.
by for now, we are using it
statically.
twitter:
@loregirardi
github:
@liqueflies
Vue.component('card-item', {
template: '#card-template',
props: ['title', 'img']
})
// ...in root component
<div id="app">
<card-item
title="Title from parent"
src="https://picsum.photos/200/300" />
</div>
https://vuejs.org/v2/components.html
… better use props
Vue.component('card-item', {
template: '#card-template',
props: ['title', 'img']
})
// ...in root component
<div id="app">
<card-item
title="Title from parent"
src="https://picsum.photos/200/300" />
</div>
https://vuejs.org/v2/components.html
… better use props
<div id="app">
<card-item
propA="..."
propB="..."
propC="..."
propD="..."
...
/>
</div>
https://vuejs.org/v2/components.html
this could be sick
Vue.component('card-item', {
inheritAttrs: false, // important to avoid unwanted markup
template: '#card-template',
props: ['title', 'img']
})
<div id="app">
<card-item v-bind="card" />
</div>
new Vue({
el: '#app',
data: {
card: { title: 'Card title', img: 'https://picsum.photos/200/300' }
}
})
https://vuejs.org/v2/components.html
v-bind to the rescue
Vue.component('card-item', {
inheritAttrs: false, // important to avoid unwanted markup
template: '#card-template',
props: ['title', 'img']
})
<div id="app">
<card-item v-bind="card" />
</div>
new Vue({
el: '#app',
data: {
card: { title: 'Card title', img: 'https://picsum.photos/200/300' }
}
})
https://vuejs.org/v2/components.html
v-bind to the rescue
lifecycle
Focusing
each vue instance goes through
a series of initialization steps
when it’s created running functions
called lifecycle hooks,
giving users the opportunity to
add their own code at specific stages.
Vue.component('card-item', {
template: '...',
data: function () {
return {
image: '...'
}
},
mounted: function () {
var image = this.image
this.image = '...my-spinner-image.png'
new imagesLoaded(this.$el, { this.image = image })
}
})
https://vuejs.org/v2/components.html
Vue.component('card-item', {
template: '...',
data: function () {
return {
image: '...'
}
},
mounted: function () {
var image = this.image
this.image = '...my-spinner-image.png'
new imagesLoaded(this.$el, { this.image = image })
}
})
https://vuejs.org/v2/components.html
Vue.component('card-item', {
template: '...',
data: function () {
return {
image: '...'
}
},
mounted: function () {
var image = this.image
this.image = '...my-spinner-image.png'
new imagesLoaded(this.$el, { this.image = image })
}
})
https://vuejs.org/v2/components.html
<div id="app">
<component :is="componentName" />
</div>
new Vue({
el: '#app',
data: {
componentName: '...'
}
})
https://vuejs.org/v2/components.html
the :is attribute
<template lang="pug">
// ...
</template>
<script>
// export default {}
</script>
<style lang="sass|scss|stylus" module|scoped>
// ...
</style>
https://vuejs.org/v2/components.html
single file
components
update
data with events
website:
https://vuejs.org/v2/style-guide/
by passing props we can mutate
child data from parent.
how can we mutate
parent data from its children?
twitter:
@loregirardi
github:
@liqueflies
<script type="text/x-template" id="slider-pag-template">
<div>
<button @click="$emit('next-slide')"> Next slide </button>
<button @click="$emit('prev-slide')"> Prev slide </button>
</div>
</script>
Vue.component('slider-pag', {
template: '#slider-pag-template'
})
<div id="app">
<slider-pag
@next-slide="slide++" @prev-slide="slide--" />
</div>
https://vuejs.org/v2/guide/components.html#Using-v-on-with-Custom-Events
<script type="text/x-template" id="slider-pag-template">
<div>
<button @click="$emit('next-slide')"> Next slide </button>
<button @click="$emit('prev-slide')"> Prev slide </button>
</div>
</script>
Vue.component('slider-pag', {
template: '#slider-pag-template'
})
<div id="app">
<slider-pag
@next-slide="slide++" @prev-slide="slide--" />
</div>
https://vuejs.org/v2/guide/components.html#Using-v-on-with-Custom-Events
and what if we want
to change data...
...wherever in the
component tree?
twitter:
@loregirardi
github:
@liqueflies
// broadcast event
var bus = new Vue()
// send event
bus.$emit('event-name', ...arguments)
// receive event
bus.$on('event-name', ...arguments)
// unbind event
bus.$off('event-name')
event bus
https://vuejs.org/v2/components.html#Content-Distribution-with-Slots
// send event
new Vue({
...
methods: {
myMethod: function () {
bus.$emit('event-name', ...arguments)
}
}
})
event bus
https://vuejs.org/v2/components.html#Content-Distribution-with-Slots
// receive event
new Vue({
...
created: function () {
bus.$on('event-name', myMethod)
},
methods: {
myMethod: function () { ... }
}
})
event bus
https://vuejs.org/v2/components.html#Content-Distribution-with-Slots
native
transitions
website:
https://vuejs.org/v2/guide/transitions.html
transitions
Focusing
transition component allows
to add enter/leave effects to:
- conditions (v-if / v-show)
- dynamic components
- component root node
- switching :key attribute
website:
https://vuejs.org/v2/guide/transitions.html
website:
https://vuejs.org/v2/guide/transitions.html
<div id="app">
<transition name="fade">
<p v-show="visible"> I am visible. </p>
</transition>
<button @click="visible = !visible"> toggle </button>
</div>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
https://vuejs.org/v2/guide/syntax.html
<div id="app">
<transition name="fade">
<p v-show="visible"> I am visible. </p>
</transition>
<button @click="visible = !visible"> toggle </button>
</div>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
https://vuejs.org/v2/guide/syntax.html
<div id="app">
<transition name="fade">
<p v-show="visible"> I am visible. </p>
</transition>
<button @click="visible = !visible"> toggle </button>
</div>
<style>
.fade-enter-active {
transition: opacity .2s ease;
}
.fade-leave-active {
transition: opacity .3;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
https://vuejs.org/v2/guide/syntax.html
<div id="app">
<transition name="fade">
<p v-show="visible"> I am visible. </p>
</transition>
<button @click="visible = !visible"> toggle </button>
</div>
<style>
.fade-enter-active {
transition: opacity .2s ease;
}
.fade-leave-active {
transition: opacity .3;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
https://vuejs.org/v2/guide/syntax.html
<div id="app">
<transition name="fade" mode="out-in|in-out">
<component :is="pageName" />
</transition>
</div>
<script>
new Vue({
el: '#app',
props: ['pageName']
})
</script>
https://vuejs.org/v2/guide/syntax.html
<div id="app">
<transition name="fade" mode="out-in|in-out">
<component :is="pageName" />
</transition>
</div>
<script>
new Vue({
el: '#app',
props: ['pageName']
})
</script>
https://vuejs.org/v2/guide/syntax.html
https://jsfiddle.net/loregirardi/52mn0sqL/
a fiddle
<div id="app">
<transition @enter="enterAnimation">
<component :is="pageName" />
</transition>
</div>
<script>
new Vue({
el: '#app',
props: ['pageName'],
methods: {
enterAnimation (el, done) { /* your code */ }
}
})
</script>
https://vuejs.org/v2/guide/syntax.html
<div id="app">
<transition @enter="enterAnimation">
<component :is="pageName" />
</transition>
</div>
<script>
new Vue({
el: '#app',
props: ['pageName'],
methods: {
enterAnimation (el, done) { /* your code */ }
}
})
</script>
https://vuejs.org/v2/guide/syntax.html
async call
best practices
website:
https://vuejs.org/
in real use cases
we have to display
data from server.
what’s the better way
to achieve that?
twitter:
@loregirardi
github:
@liqueflies
<script src="vue.js"></script>
<ul id="star-wars">
<li v-for="person in people" :key="person.name">
{{ person.name }}
</li>
</ul>
<script>
new Vue({
el: '#star-wars',
data: {
people: []
},
created: function () {
fetch('https://swapi.co/api/people').then(function (response) {
this.people = response.results
})
}
})
</script>
<script src="vue.js"></script>
<ul id="star-wars">
<li v-for="person in people" :key="person.name">
{{ person.name }}
</li>
</ul>
<script>
new Vue({
el: '#star-wars',
data: {
people: []
},
created: function () {
fetch('https://swapi.co/api/people').then(function (response) {
this.people = response.results
})
}
})
</script>
in fast connections
we will immediately see
results.
how can we add a loader
for slow connections?
twitter:
@loregirardi
github:
@liqueflies
https://jsfiddle.net/loregirardi/5x6392wr/
a fiddle
five
reasons why
website:
https://vuejs.org/
no build steps
required
Easy to start up, also in old legacy
projects.
website:
https://vuejs.org/
effortless
api
update and modify data is easy.
context is auto-binded and rendering
updates are out of the box.
website:
https://vuejs.org/
add modularly
what you need
if your app / website needs to scale
just add modules from vue.js ecosystem
to fit your needs.
website:
https://vuejs.org/
no es6 knowledge
needed
i am not telling you to not learn es6.
but if you want you can still use
old es2015 syntax so
beginner / not-frontend dev
can easily get into it.
website:
https://vuejs.org/
super fast on
mobile devices
is easy achieve fast rendering on desktop,
vue.js get the best experience on mobile
devices.
website:
https://vuejs.org/
useful resources
- curated list: https://github.com/vuejs/awesome-vue
- official forum: https://forum.vuejs.org/
- vuex: https://github.com/vuejs/vuex
- vue-router: https://router.vuejs.org/en/
- vue-cli: https://github.com/vuejs/vue-cli
- server-side rendering: https://vuejs.org/v2/guide/ssr.html
website:
https://vuejs.org/
vue people
- evan you: https://twitter.com/youyuxi
- kazupon: https://twitter.com/kazu_pon
- linusborg: https://twitter.com/Linus_Borg
- akryum: https://twitter.com/Akryum
- katashin: https://twitter.com/ktsn
- sarah drasner: https://twitter.com/sarah_edo
website:
https://vuejs.org/team.html
vue community is
growing quickly but is recent.
let’s share knowledge,
code and passion.
twitter:
@loregirardi
github:
@liqueflies
thank you

Level up apps and websites with vue.js

Editor's Notes

  • #3 BENVENUTI AL NUOVO INCONTRO DEL COMMIT UNIVERSITY ->
  • #4 24 anni da verona ->
  • #5 ed è un piacere essere qui ->
  • #9 sondaggio quando vecchi amici chiedono che lavoro fai...
  • #12 ci siamo resi conto che il problema era gestire lo stato della nostra applicazione ->
  • #17 i numeri sono raddoppiati dallo scorso anno ->
  • #19 dobbiamo pensare che la vista sia la rappresentaziobne visiva del nostro stato, il nostro compito è quello di eseguire i cambiamenti su di esso
  • #20 le proprietà di data hanno un setter ed un getter ciascuna, vengono collezionati in watcher che vengono notificati dai setter per triggerare nuovamente il render del layout
  • #22 Espressione javascript tra mustache syntax
  • #26 Espressione javascript tra attributi html
  • #30 differenze v-if per nascondere ciò che non vogliamo vedere v-show per nascondere momentaneamente qualcosa che poi sarà visibile costo di esecuzione maggiore per v-if
  • #32 prendere ogni cella dell’array todos ed averla a disposizione dal nodo su cui viene applicato il v-if e anche al suo interno
  • #35 eventi direttamente nell’html
  • #37 v-model viene applicato in qualsiasi tipo di input, al suo evento change la modifica viene propagata alla proprietà di data sul quale abbiamo applicato l’attributo
  • #40 vantaggio sequenziale, una dipende dall’altra
  • #44 computed è una proprietà dell’oggetto vue deve ritornare una variabile / dato viene chiamata come una prop di data è cachata se non vengono aggiornate dipendenze
  • #47 è una chiave dell’oggetto vue è una funzione che non deve ritornare per forza un valore, solitamente muta delle proprietà non è cachata
  • #53 spesso la definizione di component e la sua utilità non vengono concretamente comprese
  • #55 chiaramente header e footer non saranno riutilizzabili ma il singolo post del blog probabilmente si
  • #56 un insieme di tag html accessibili da un unico nodo ognuno con riferimento al proprio stile e la propria logica