Laravel

Un framework qui rend heureux

Voir cette catégorie
Vers le bas
Vue.js : Action !
Vendredi 5 février 2016 17:56

Je vous ai dit dans le premier article que vue.js est destiné à créer des interfaces interactives. Pour le moment je ne vous l'ai pas encore prouvé ! Dans cet article on va voir comment on gère les actions de l'utilisateur.

La directive v-on

Pour intercepter les événements survenant au niveau de la vue vue.js offre la directive v-on.

Prenons un petit exemple pour introduire cette notion :

<div id="tuto">
  <a v-on:click="action">Cliquez ici !</a>
</div>

On a mis la directive v-on  dans la balise a. Notez la syntaxe : on fait suivre le nom de la directive de deux points , du nom de l'événement, puis du nom d'une fonction. On comprend vite qu'on va appeler la fonction lorsqu'on va cliquer sur le lien.

Voici le code Javascript :

new Vue({
  el: '#tuto',
  methods: {
    action: function () {
      alert('On a cliqué !');
    }
  }
});

Nous découvrons une propriété pas encore rencontrée : methods. C'est ici qu'on va placer les méthodes de la VueModèle. Ici on a besoin d'une méthode action pour répondre à l'événement de clic.

Le résultat au clic est donc l'ouverture de la petite fenêtre d'information :

img01

Voici une illustration de la liaison :

img12

On commence à avoir de l'interactivité !

On peut aussi, au lieu d'une fonction, utiliser une expression comme argument de la directive v-on. Voici un exemple :

<div id="tuto">
  <h1> 
    <button class="button btn-primary" v-on:click="++n">+</button> {{ n }}
  </h1>
</div>

Cette fois on utilise un bouton et le même événement click. Mais au lieu d'une fonction on se contente d'incrémenter la variable n. D'autre part on affiche la valeur de cette variable avec mustache.

Voici le Javascript :

new Vue({
  el: '#tuto',
  data: { n: 0 }
});

On initialise n avec la valeur 0 et on sait que sa valeur sera systématiquement répercutée dans la vue. Donc chaque fois qu'on clique sur le bouton la valeur affichée s'incrémente. Voilà l'aspect obtenu :

img03

Un bouton pour incrémenter une valeur

Voici une schématisation du fonctionnement :

img13

Un survol

Tous les événements disponibles avec Javascript le sont évidemment aussi avec vue.js, ce qui ouvre pas mal de perspectives au niveau de l'interactivité. Prenons un petit exemple pour un changement d'aspect au survol. Voici la vue :

<div id="tuto">
  <h1> 
    <span class="label label-{{type}}" v-on:mouseover="changeType">{{type}}</span>
  </h1>
</div>

On voit une petite nouveauté avec du mustache dans les attributs. Autrement dit on va pouvoir changer de façon dynamique la valeur d'un attribut. D'autre part cette fois l'événement utilisé est mouseover, autrement dit le déclenchement va avoir lieu au survol de l'élément par le curseur de la souris.

Voici le Javascript :

new Vue({
  el: '#tuto',
  data: {
    type: 'primary'
  },
  methods: {
    changeType: function() {
      this.type = (this.type == 'primary') ? 'success' : 'primary';
    }
  }
});

On a dans les données la propriété type qui au départ a la valeur "primary". A chaque survol de l'étiquette par le curseur de la souris cette valeur va changer, alternant entre "primary" et "success". Du coup l'aspect à l'écran va aussi changer en conséquence. D'autre part on modifie aussi le texte de l'étiquette qui est relié à la même propriété.

Donc au départ on a :

img05

Et ensuite :

img06

Et ainsi de suite à chaque survol...

Voici une illustration du fonctionnement :

img14

Le chronomètre

On va poursuive l'exemple du chronomètre vu lors du précédent chapitre en lui ajoutant de l'interactivité. On va en profiter au passage pour découvrir la directive v-show très utile qui permet de masquer des éléments du DOM à l'affichage. Voici la nouvelle version complète :

<!DOCTYPE html>
<html lang="fr">

  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Test vue.js</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
  </head>

  <body>

    <div class="container">

      <div id="tuto" class="text-center">
        <h1>Le chronomètre</h1>
        <hr>
        <h1>
          <span class="label label-primary">{{ time.minutes }}</span> minutes
          <span class="label label-primary">{{ time.secondes }}</span> secondes
        </h1>
        <br>
        <p>
          <button class="btn btn-danger btn-lg" v-show="etat.backward" v-on:click="backward">Effacer</button>
          <button class="btn btn-danger btn-lg" v-show="etat.stop" v-on:click="stop">Arrêter</button>
          <button class="btn btn-primary btn-lg" v-show="etat.play" v-on:click="play">{{ btnPlay }}</button>
        </p>
      </div>

    </div>

    <script src="http://cdn.jsdelivr.net/vue/1.0.10/vue.min.js"></script>

    <script>

      var vm = new Vue({
        el: '#tuto',
        data: {
          time: {
            minutes: 0,
            secondes: 0
          },
          btnPlay: 'Démarrer',
          etat: {
            stop: false,
            backward: false,
            play: true
          }
        },
        methods: {
          backward: function() {
            chronoReset();
          },
          play: function() {
            chronoStart();            
          },
          stop: function() {
            chronoStop();
          }
        }
      });

      var totalSecondes = 0;
      var timer;

      chronoStart = function() {
        timer = setInterval(function() {
          vm.time.minutes = Math.floor(++totalSecondes / 60);
          vm.time.secondes = totalSecondes - vm.time.minutes * 60;
        }, 1000);
        setEtat(false, true, false);
        vm.btnPlay = 'Continuer';
      };

      chronoStop = function() {
        clearInterval(timer);
        setEtat(true, false, true);
      };

      chronoReset = function() {
        totalSecondes = 0;
        vm.time.minutes = 0;
        vm.time.secondes = 0;
        setEtat(true, false, false);
        vm.btnPlay = 'Démarrer';        
      }

      setEtat = function(play, stop, backward) {
        vm.etat.play = play;
        vm.etat.stop = stop;
        vm.etat.backward = backward;        
      };

    </script>

  </body>

</html>

La vue

Voici la partie HTML :

<div id="tuto" class="text-center">
  <h1>Le chronomètre</h1>
  <hr>
  <h1>
    <span class="label label-primary">{{ time.minutes }}</span> minutes
    <span class="label label-primary">{{ time.secondes }}</span> secondes
  </h1>
  <br>
  <p>
    <button class="btn btn-danger btn-lg" v-show="etat.backward" v-on:click="backward">Effacer</button>
    <button class="btn btn-danger btn-lg" v-show="etat.stop" v-on:click="stop">Arrêter</button>
    <button class="btn btn-primary btn-lg" v-show="etat.play" v-on:click="play">{{ btnPlay }}</button>
  </p>
</div>

Pour simplifier je n'ai gardé que les minutes et secondes, ce qui est réaliste pour un chronomètre. On utilise 2 étiquettes avec une liaison "mustache". On trouve également 3 boutons de commandes avec pour chacun :

  1. une directive v-on pour détecter l'événement click

  2. un directive v-show pour pouvoir changer la visibilité du bouton

D'autre part le troisième bouton a son texte avec une liaison "mustache", il pourra donc changer de nom.

Le Javascript

Voyons la partie Javascript. D'abord la déclaration propre à vue.js :

var vm = new Vue({
  el: '#tuto',
  data: {
    time: {
      minutes: 0,
      secondes: 0
    },
    btnPlay: 'Démarrer',
    etat: {
      stop: false,
      backward: false,
      play: true
    }
  },
  methods: {
    backward: function() {
      chronoReset();
    },
    play: function() {
      chronoStart();            
    },
    stop: function() {
      chronoStop();
    }
  }
});

On trouve :

  • la liaison avec l'élément du DOM : #tuto

  • le modèle (data) avec 3 propriétés :

  1. time : 2 propriétés pour les minutes et secondes du chronomètre

  2. btnPlay : pour le texte du bouton (Démarrer/Continuer)

  3. etat : 3 propriétés pour la visibilité des 3 boutons

  • les méthodes :

  1. backward : pour remettre le chronomètre à 0

  2. play : pour lancer ou relancer le chronomètre

  3. stop : pour arrêter le chronomètre

On a ensuite les variables globales et les fonctions de gestion :

var totalSecondes = 0;
var timer;

chronoStart = function() {
  timer = setInterval(function() {
    vm.time.minutes = Math.floor(++totalSecondes / 60);
    vm.time.secondes = totalSecondes - vm.time.minutes * 60;
  }, 1000);
  setEtat(false, true, false);
  vm.btnPlay = 'Continuer';
};

chronoStop = function() {
  clearInterval(timer);
  setEtat(true, false, true);
};

chronoReset = function() {
  totalSecondes = 0;
  vm.time.minutes = 0;
  vm.time.secondes = 0;
  setEtat(true, false, false);
  vm.btnPlay = 'Démarrer';        
}

setEtat = function(play, stop, backward) {
  vm.etat.play = play;
  vm.etat.stop = stop;
  vm.etat.backward = backward;        
};

Le fonctionnement

Au départ on a cet aspect :

img08

Lorsqu'on clique sur le bouton "Démarrer" le chronomètre se met en marche. Au niveau des boutons "Démarrer" disparaît et "Arrêter" apparaît :

img09

Lorsqu'on clique sur "Arrêter" le comptage s'interrompt, le bouton "Arrêter" disparaît. Les boutons "Effacer" et "Continuer" apparaissent :

img10

Si on clique sur "Effacer" on revient à la situation de départ et si on clique sur "Continuer" le comptage reprend et le bouton "Arrêter" réapparaît.

En résumé

  • On gère les événements avec la directive v-on.

  • On masque les éléments du DOM avec la directive v-show .



Par bestmomo

Aucun commentaire