Introduction à
Par Sébastien Rodriguez
@sebtiz13
Who I am
- Développeur chez Laëtis
- Développeur front/backend PHP et JS
- Éternel perfectionniste et optimiseur
Bref historique
Créer par Evan YOU ancien développeur chez Google
- Février 2014 : Vue.js est inspiré de la partie vue de AngularJS
- Octobre 2015 : Version 1.0 réécriture de l'API
- Décembre 2015 : Vue-cli
- Septembre 2016 : Version 2.0 Virtual-DOM et Server-Side Rendering
Qu'est-que c'est ?
- Axer sur l'interface
- Composants
- Rechargement à chaud
- Débogage temporel
- Apprentissage incrémentale
Qui l'utilise ?
Un exemple ?
Un peu de lexique
-
Directives
-
Models
-
Computed (propriétés calculées)
-
Watchers (observateurs)
-
State (état)
-
Modifiers (modificateurs)
Comment ça marche ?
Avant de débuter
Révisions ES6
Déclaration de variables
function fn() {
let foo = "bar"
var foo2 = "bar"
if (true) {
let foo // pas d'erreur, foo === undefined
var foo2 // Les déclarations "var" ne sont pas scopées au niveau bloc foo2 est en réalité écrasée !
foo = "qux"
foo2 = "qux"
console.log(foo) // "qux", la variable appartient au scope de son blocs (le "if")
console.log(foo2) // "qux"
}
console.log(foo) // "bar", la variable appartient au scope de son bloc (la fonction "fn")
console.log(foo2) // "qux"
}
let is a new var
Fonctions fléchées
let double = number => number * 2 // Le return est implicite
double(5) // 10
this.divClicked = false
document.querySelector('div').addEventListener('click', event => {
event.preventDefault()
this.divClicked = true
// Some code
})
(arrow function)
var double = function (number) {
return number * 2
}
double(5) // 10
this.divClicked = false
document.querySelector('div').addEventListener('click', function (event) {
event.preventDefault()
this.divClicked = true
// Some code
}.bind(this))
find / findIndex
let ages = [12, 19, 6, 4]
let firstAdult = ages.find(age => age >= 18) // 19
let firstAdultIndex = ages.findIndex(age => age >= 18) // 1
Opérateur de diffusion
let numbers = [9, 4, 7, 1]
Math.min(...numbers) // 1
// Math.min(9, 4, 7, 1)
// Convertis NodeList en Array
let divsArray = [...document.querySelectorAll('div')]
// Fusion d'objet
let object = { tata: 'tata', toto: 'toto' }
let newObject = { ...object, titi: 'titi' }
// newObject : { tata: 'tata', toto: 'toto', titi: 'titi' }
(spread operator)
Décomposition des objets
let user = {
firstname: 'Michel',
lastname: 'Dupont',
nickname: 'titi'
}
// pseudo est changé en username et on récupère firstname
function sayFirstName ({ nickname: username, firstname }) {
console.log(lastname) // undefined
return 'Le prénom de ' + username + ' est ' + firstname
}
sayFirstName(user) // Le prénom de titi est Michel
Syntaxe raccourcie
// Raccourcis pour les noms de propriétés
var a = "toto", b = 42, c = {}
var o = { a, b, c }
// Raccourcis pour les noms de méthodes
var o = {
mafonction: function () {}
mafonction () {}
}
// Noms calculés pour les propriétés
var prop = "toto"
var o = {
[prop]: "hey",
["tr" + "uc"]: "ho",
}
C'est parti pour les bases !
L'instance
...
<div id="app">
<!-- Vue.JS -->
</div>
...
<script>
let app = new Vue({
el: '#app'
})
</script>
Les variables
...
<div id="app">
{{ message }}
</div>
...
<script>
let app = new Vue({
el: '#app',
data: {
message: 'Hello Vue !'
}
})
</script>
Les directives
...
<div id="app">
<img v-bind:src="image" />
<img :src="image" /> <!-- syntaxe courte -->
</div>
...
<script>
let app = new Vue({
el: '#app',
data: {
image: 'https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-580335.jpg'
}
})
</script>
Les conditions
...
<div id="app">
<div v-if="!image">
Oh noooon !
</div>
<img v-else src="https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-509703.png"/>
<img v-show="isRed" src="https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-377340.jpg"/>
</div>
...
<script>
let app = new Vue({
el: '#app',
data: {
image: true
isRed: false
}
})
</script>
Les boucles
...
<div id="app">
<ul>
<li v-for="name in users">{{ name }}</li>
</ul>
</div>
...
<script>
let app = new Vue({
el: '#app',
data: {
users: [ 'toto', 'titi', 'tata' ]
}
})
</script>
Les évènements
...
<div id="app">
<button v-on:click="alertYou" >Click me !</button>
<button @click="alertYou" >Click me !</button> <!-- syntaxe courte -->
</div>
...
<script>
let app = new Vue({
el: '#app',
methods: {
alertYou () {
alert('Hey you')
}
}
})
</script>
Modificateurs d'évènements
<div id="app">
<!-- La propagation de l'évènement `click` sera stoppée -->
<a @click.stop></a>
<!-- L'évènement `submit` ne rechargera plus la page -->
<form @submit.prevent></form>
<!-- L'évènement ne s'applique qu'à l'élément pas aux enfants -->
<div @click.self="doThat">...</div>
<!-- Appel submit() quand on appuis sur la touche entrée -->
<input @keyup.enter="submit">
<!-- Utilise le mode "capture" de addEventListener -->
<!-- (l'évènement est lancé avant celui des enfants) -->
<div @click.capture="alert('Capture')">
<button @click="alert('Hello world')">Click me</button>
</div>
<!-- 2.1.4+ : L'évènement n'est lancé qu'une fois -->
<div @click.once="sayHello">...</div>
</div>
Les modèles
...
<div id="app">
<input v-model="message">
{{ message }}
</div>
...
<script>
let app = new Vue({
el: '#app'
data: {
message: 'I am watching you'
}
})
</script>
Modificateurs de modèles
<div id="app">
<!-- synchronisé après le "change" au lieu du "input" -->
<input v-model.lazy="message">
<!-- Force le type number -->
<input v-model.number="age" type="number">
<!-- Supprime les espaces superflus -->
<input v-model.trim="message">
</div>
Les transitions
...
<div id="app">
<button @click="show = !show"> Permuter </button>
<transition name="fade">
<p v-if="show">Hello world</p>
</transition>
</div>
...
<script>
let app = new Vue({
el: '#app'
data: {
show: true
}
})
</script>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
Observateurs
&
Propriétés calculées
Les observateurs
...
<div id="app">
{{ fullName }}
</div>
...
<script>
let app = new Vue({
el: '#app'
data: {
firstName: 'Toto',
lastName: 'Tata',
fullName: 'Toto Tata'
},
watch: {
firstName (val) {
this.fullName = val + ' ' + this.lastName
},
lastName (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
</script>
Propriétés calculées
...
<div id="app">
{{ fullName }}
</div>
...
<script>
let app = new Vue({
el: '#app'
data: {
firstName: 'Toto',
lastName: 'Tata'
},
computed: {
fullName () {
return this.firstName + ' ' + this.lastName
}
}
})
</script>
Gestion des formulaires
Input
...
<div id="app">
<input v-model="messsage" placeholder="Saisir un message">
<span>Message: {{ messsage }}</span>
</div>
...
<script>
let app = new Vue({
el: '#app',
data: {
messsage: ''
}
})
</script>
Checkbox
...
<div id="app">
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<span>Noms cochés: {{ checkedNames }}</span>
</div>
...
<script>
let app = new Vue({
el: '#app',
data: {
checkedNames: []
}
})
</script>
Radio
...
<div id="app">
<input type="radio" id="jack" name="name" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="radio" id="john" name="name" value="John" v-model="checkedNames">
<label for="john">John</label>
<span>Noms choisi: {{ checkedName }}</span>
</div>
...
<script>
let app = new Vue({
el: '#app',
data: {
checkedName: ''
}
})
</script>
Liste déroulante
...
<div id="app">
<select v-model="selected">
<option value="123">123</option>
<option value="256">256</option>
</select>
<span>Montant {{ selected }}</span>
</div>
...
<script>
let app = new Vue({
el: '#app',
data: {
selected: 0
}
})
</script>
Passer une valeur litérale
...
<div id="app">
<label for="check">Check me :</label>
<input type="checkbox" value="{ text: 'Hello world' }" v-model="message" id="check">
{{ message }} <!-- [ "{ text: 'Hello world' }" ] -->
</div>
...
<script>
let app = new Vue({
el: '#app',
data: {
message: []
}
})
</script>
Les composants
La création
...
<div id="app">
<my-component></my-component>
</div>
...
<script>
let myComponent = Vue.component('my-component', {
template: '<div>Un composant personnalisé !</div>'
})
let app = new Vue({
el: '#app',
components: {
myComponent
}
})
</script>
Limitation avec le DOM
<!-- Erreur ! -->
<table>
<my-row>...</my-row>
</table>
<!-- Solution ! -->
<table>
<tr is="my-row"></tr>
</table>
<ul>, <ol>, <table>, <select>, <option>
Data doit être une fonction
...
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
...
<script>
Vue.component('my-component', {
template: '<span>{{ message }}</span>',
data: {
message: 'bonjour' // Warning : Même objet !
}
})
...
</script>
La Composition
descente de props, remontée d’évènements.
Les propriétés
...
<div id="app">
<my-component message="bonjour !"></my-component>
</div>
...
<script>
Vue.component('my-component', {
props: ['message'],
template: '<span>{{ message }}</span>'
})
...
</script>
Littérales vs dynamiques
<div id="app">
<!-- Ceci est un String "1" -->
<comp some-prop="1"></comp>
<!-- Ceci est un Number 1 -->
<comp :some-prop="1"></comp>
</div>
Validation des propriétés
Vue.component('child', {
props: {
propA: String,
propB: [String, Number],
propC: { type: String, required: true }
propD: { type: String, default: 'Hello world' }
propE: { type: Object, default () { return { message: 'hello' } } }
propF: {
validor (value) {
return (value / 10) > 10
}
}
}
})
Les slots
<!-- Utilisation -->
<div>
<h1>Je suis le titre du parent</h1>
<my-component>
<p>Ceci est le contenu original</p>
</my-component>
</div>
<!-- Composant -->
<div>
<h2>Je suis le titre de l'enfant</h2>
<slot> Serra remplacé </slot>
</div>
<!-- Résultat -->
<div>
<h1>Je suis le titre du parent</h1>
<div>
<h2>Je suis le titre de l'enfant</h2>
<p>Ceci est le contenu original</p>
</div>
</div>
Les slots nommés
<!-- Utilisation -->
<app-layout>
<h1 slot="header">Voici un titre de page</h1>
<p>Un paragraphe pour le contenu principal.</p>
<p>Et un autre.</p>
<p slot="footer">Ici plusieurs informations de contact</p>
</app-layout>
<!-- Composant -->
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
Les évènements personnalisés
...
<div id="app">
<child @hello="alert('Enfant dit bonjour')"></child>
</div>
...
<script>
Vue.component('child', {
props: ['message'],
template: '<button @click="sayHello">Dire bonjour</button>'
methods: {
sayHello () {
this.$emit('hello')
}
}
})
...
</script>
Aller plus loin
Composants monofichiers
<template>
<p>Hello {{ name }}</p>
<button @click="sayHello">Dire bonjour</button>
</template>
<script>
export default {
data () {
return {
name: 'Jon Snow'
}
}
methods: {
sayHello () {
alert(`You don't know`)
}
}
}
</script>
<style scoped>
p {
font-size: 2rem;
}
</style>
Routeur
...
<div>
<nav>
<!-- `<router-link>` sera rendu en tag `<a>` par défaut -->
<router-link to="/foo">Aller à Foo</router-link>
<router-link to="/bar">Aller à Bar</router-link>
</nav>
<!-- La page sera rendu ici -->
<router-view></router-view>
</div>
...
<script>
const router = new VueRouter({
routes: [
{ path: '/foo', component: { template: '<div>foo</div>' } },
{ path: '/bar', component: { template: '<div>bar</div>' } }
]
})
const app = new Vue({
router
}).$mount('#app')
</script>
(vue-router)
Validation de formulaire
import { required, minLength } from 'vuelidate/lib/validators'
export default {
data () {
return {
name: ''
}
},
validations: {
name: {
required, // Name est requis
minLength: minLength(4) // Minimum 4 lettres
}
}
}
(vuelidate)
Internationalisation
(vue-i18n)
...
<div id="app">
<p>{{ $t("message") }}</p> <!-- hello world -->
</div>
...
<script>
const messages = {
en: {
message: 'hello world'
},
fr: {
message: 'Bonjour tout le monde'
}
}
const i18n = new VueI18n({
locale: 'en', // Définit la langue
messages, // Initialise le dictionnaire
})
const app = new Vue({ i18n }).$mount('#app')
</script>
Gestion d'état centralisé
(vuex)
Rendu côté serveur
(Nuxt.js)
Conclusion
Les avantages
- Code très lisible avec les .vue
- Code maintenable
- Scalabilité
- Apprentissage incrémentale
La popularité grandissante
Merci !
Introduction Vue.js
By sebtiz13
Introduction Vue.js
Vue.js est un framework javascript front-end qui permet de créer facilement des interfaces réactivent dans un navigateur web, ainsi que des applications mobile. (sur youtube : https://www.youtube.com/watch?v=btRWtnA8irQ)
- 1,687