Vue.js
Data-reactive web components
Bonjour, je m'appelle Eduardo et aujourd'hui je vais vous parler de
vuejs. Un framework MVVM que j'ai découvert il y a quelques mois, que
j'utilise depuis et lequel me plait de plus en plus.
Another MV* ?!
j'ai dit que c'était un framework MVVM. C'est vrai qu'il y en a
plein. C'est comme si tout le monde avait vu Angular, s'était dit
"C'est stylé de faire des applis comme ça, mais j'aimerais X" ou je
n'aime pas Y". Et du coup tout le monde a eu envie de faire son
propre Framework. Certains l'on fait, d'autres se sont dit qu'ils
avaient pas le temps (la classique). Et du coup plus de 20 frameworks
existent aujourd'hui. Tels que Angular, React, Aurelia, Angular2,
Mithril et aussi Vuejs.
Why Vue ?
- Balance between Performance – Usability
- Components oriented
- Very active community!
Et si je parle de Vuejs aujourd'hui c'est parce que ce framework
établi un Equilibre entre performance et Usabilité. Je dirait meme
qu'il arrive a trouver le compromis que React et Angular manquent.
C'est orienté composants ou components en anglais. j'en reparlerai
plus tard
Issues crées tous les jours (un peu moins les we) et tout le monde qui répond
chat Gitter pour discuter ou demander de l'aide
Documentation solide
tout ça pour componser un manque de questions sur stack overflow
Hello World
<div id="hello-world">
<input v-model="value" type="text"/>
<p>{{value}}</p>
</div>
new Vue({
el: '#hello-world',
data: {
value: 'Hello World'
}
});
{{value}}
On va directement passer à un hello world. Je vais à chaque fois
on créé un vm pour lier div et data, une directive pour input
Vocabulary
Il y qq nouveaux mots. On va donc en parler
Anvant de rentrer un peu plus dans les details de vue on va parler des
principaux termes utilisés. Il y en a pas beaucoup :D
Directives
v-model
,v-if
, ...- Custom directives(always start by v-)
<input v-model="value" type="text"/>
Tous les v- sont des directives
v-model est une directive mais type ne l est pas
The View Model (vm
)
View ⇆ Model
new Vue({...});
Le vm se charge de sync les données avec la vue
La vm est crée quand on instancie une Vue
Elle a toute la logique et ne comporte pas de manipulation du DOM(faites dans les
directives)
The View Model (vm
)
Components
Reusable modules
<contact-card></contact-card>
Props
Pass Data down to a component
<contact-card type="rounded"></contact-card>
<contact-card v-bind:contact="contact"></contact-card>
ça va remplacer le ng-class et ng-checked et plein d'autres
Ce qui est plus expressif car v-contact pourrait être une directive
Usual features
les impasses, mais avant on va parler des concepts de base de vue
v-show
/v-if
<div id="v-show">
<input v-model="show" type="checkbox"/>
<span>
{{show ? 'Hide the bear' : 'Show the bear'}}
</span>
<img v-show="show" src="images/bear-hello.gif"/>
</div>
new Vue({
el: '#v-show',
data: {
show: false
}
});
v-for
<div id="v-for">
<ul>
<li v-for="item in items">{{item}}</li>
</ul>
</div>
new Vue({
el: '#v-for',
data: {
items: [0, 1]
}
});
There are {{items.length}} elements
- {{item}}
transition
v-bind
<form v-bind:class="{'invalid-form': invalid}"></form>
<form :class="{'invalid-form': invalid}"></form>
Events(v-on)
<form v-on:submit="send()"></form>
<form @submit="send()"></form>
<button @click="select(contact)">Select</button>
Vue js fonctionne avec des events en interne. On peut emmettre
des evenements sur des components qui remontent vers les parents
Filters
Adapt the model to the view
<div id="filters">
<p>{{obj | json}}</p>
</div>
new Vue({
el: '#filters',
data: {
obj: {
bool: true,
arr: [1, 2],
inner: {
a: null
}
}
}
});
{{obj | json}}
quand on veut modifier les données avant de les afficher
on peut les chainer les un à la suite des autres
On peut passer des argument
et on peut bien sur creer ses propres filtres
That's all ?
Il manque bien sur plein de trucs. c'est pour ca que lon utilise des plugins.
On evite de construire une usine a gaz
The Rules
elles sont la pour faire que le dev n'ai pas a se poser de questions
lorsqu'il doit écrire du code.
réactif = prend une expression
Directives are by default reactive
<a v-link="/foo">Go to foo</a>
<a v-link="'/foo'">Go to foo</a>
<a v-link.literal="/foo">Go to foo</a>
Tout ça dans le but d'être consistent et lisible
Attributes and props are by default non reactive
<img src="images/default-user.png"/>
<img :src="user.picture"/>
<contact-card :contact="user"></contact-card>
Ce qui a du sens pour les props car ça veut être la même chose
vue sait que c'est un lien et qu'il faut faire une requete
Mustache binding
Text interpolation
<p>URL is {{imgUrl}}</p>
Component System
Pros
- DRY(Don't repeat yourself)
- Better structure
- Better readability
j'ai parlé tout à l'heure des components comme un avantage. mais pourquoi
ça incite la refacto car on peut bien commencer par un component qui contient tout
Puis au fur et a mesure que l'appli avance on se rend compte que certain composants
peuvent etre reutilisés
One page mess
<div id="contacts">
<form id="contacts-search" @submit="fetchResults()">
<input v-model="search" type="text"/>
<button type="submit">Search</button>
</form>
<div id="contacts-results" class="contacts-grid">
<div class="contacts-card row" v-for="contact in contacts">
<img :src="contact.imgUrl" class="contacts-img col-4"/>
<div class="contacts-info col-8">
<span>{{contact.firtsName}} {{contact.lastName}}</span>
</div>
</div>
</div>
</div>
Search and contact-grid components
<div id="contacts">
<search id="contacts-search" :submit="fetchResults"></search>
<contact-grid id="contacts-results" :contacts="contacts">
</contact-grid>
</div>
Componentception: contact-grid
<div class="contacts-grid">
<contact-card v-for="contact in contacts"
:contact="contact">
</contact-card>
</div>
Binding modes
:prop='defaultOneWay'
:prop.sync='twoWay'
:prop.once='oneTime'
<mdl-checkbox :checked.sync="confirm">Confirm</mdl-checkbox>
Le sync est tres utile lorsque l'on crée des composants tels que des checkboxs
Hooks
created, beforeCompile, compiled, ...
ready: function() {
componentHandler.upgradeElement(this.$el);
}
vue
format
il y a du template, du js et meme du style
Inline template
var MyComponent = Vue.extend({
template: '<p>I'm a component!</p>'
});
Gather your HTML with your js
<template> <div class="contacts-card row" v-for="contact in contacts"> <img :src="contact.imgUrl" class="contacts-img col-4"/> <div class="contacts-info col-8"> <span>{{contact.firtsName}} {{contact.lastName}}</span> </div> </div> </template>
<script>
module.exports = { props: { contact: { type: Object, required: true } } };
</script>
Gather your pug(jade) with your js
<template lang="jade">
.contacts-card.row(v-for'contact in contacts') img.contacts-img.col-4(:src='contact.imgUrl') .contacts-info.col-8 span {{contact.firtsName}} {{contact.lastName}}
</template>
<script lang="coffee">
module.exports = props: contact: type: Object required: true
</script>
Add the style
<template lang="jade">
...
</template>
<style lang="stylus">
.contacts-card ... .contacts-info ...
</style>
<script lang="coffee">
...
</script>
Compiling vue
filse into js
- Browserify:vueify
- Webpack:vue-loader