Loupe

Implémenter facilement Vuex avec le plugin Vuex-ORM !

Bonjour à tous,

J'ai récemment remarqué que mettre en place Vuex dans un projet Vue.js peut-être rapidement laborieux :

  • Définir dans vos modules les states, les getters, les actions, les mutations...
  • Importer MapGetter et MapActions dans vos composants...
  • ... et Vuex ne gère pas nativement les relations entre objets.

En essayant de chercher des exemples d'implémentation de Vuex "natif" dans des projets Vue.js, je suis tombé par hasard sur un repo github "vuex-orm" accompagné d'un exemple d'application de création d'utilisateur et de todolist.

Je suis alors allé voir les modules dans le dossier "store" et là ... aucun module. Je vais donc voir dans le dossier "model", j'en trouve deux : User.js et Todo.js mais aucun state, getter, action ou mutation de défini !? ...

... "belongsTo()" ? "hasOne()" ? Wow... il serait donc possible de faire du Vuex sans écrire du Vuex juste en définissant nos modèles et les relations entre eux ? Ça, c'est beau.

Je vous propose alors de décourvrir Vuex-ORM ou "comment implémenter Vuex facilement" avec ce plugin qui gère des entités javascript à la manière d'une base de donnée relationnelle ! 

Dépendances

npm install vue vuex @vuex-orm/core

Ajouter Vuex-ORM à votre projet Vue.js

Pour la suite de cet article, je prendrai comme exemple ce repertoire Github qui implémente déjà Vuex-ORM.

Dans l'exemple que nous prenons, il n'y a pas d'appel API mais Vuex-ORM prend tout à fait en charge l'utilisation d'Axios. (Vous retrouverez toutes les informations à ce sujet dans cette documentation.)

screenshot.png

L'application présente les fonctionnalités suivantes :

  • créer des utilisateurs
  • créer des tâches à effectuer
  • assigner une tâche à un utilisateur
  • voir combien de tâches sont assignées à un utilisateur
  • supprimer des utilisateurs et des tâches

Vuex-ORM utilise un dossier "models" où sont définis les modèles de données de votre application. Dans notre cas, User.js et Todo.js.

User.js

import { Model } from '@vuex-orm/core'
import Todo from './Todo'

export default class User extends Model {
  static entity = 'users'

  static fields () {
    return {
      id: this.uid(),
      name: this.string(''),
      todos: this.hasMany(Todo, 'user_id')
    }
  }
}

Pour définir un Model avec Vuex-Orm il faut définir une classe qui hérite de Model.

static entity = 'users' indique que notre pseudo base de donnée contiendra une table 'users'. La liste de nos utilisateurs sera accessible par 'store.state.entities.users' ! Le state est créé automatiquement par Vuex-Orm.

Les propriétés de notre User sont définies via fields(). Ici, notre utilisateur a un id qui sera automatiquement généré via .uid(), un nom dont la valeur par défaut sera une chaîne de caractères vide ainsi que des tâches (todos) avec une relation 1-N "hasMany()" qui indique explicitement qu'un utilisateur peut avoir plusieurs tâches qui lui sont associées.

Vous retrouverez l'ensemble des attributs de champs tel que: this.attr(), this.number(), this.boolean() dans la documentation.

Intéressons-nous maintenant au model Todo.js.

Todo.js

import { Model } from '@vuex-orm/core'
import User from './User'

export default class Todo extends Model {
  static entity = 'todos'

  static fields () {
    return {
      id: this.uid(),
      user_id: this.string(null).nullable(),
      title: this.string(''),
      done: this.boolean(false),
      assignee: this.belongsTo(User, 'user_id')
    }
  }
}

Vous devriez être maintenant familier avec la syntaxe de Vuex-Orm mais je pense que vous avez remarqué l'attribut de champ .belongsTo(User, 'user_id')...

En effet, une Todo appartient à un User, donc notre Model a un attribut "user_id" (une clé étrangère), et pour indiquer à Vuex-Orm la relation 1-1 entre un User et une Todo nous utilisons .belongsTo()

Vuex-Orm utilise également une pseudo base de donnée que vous trouverez dans le dossier "database". C'est ici que l'on ajoutera nos modèles à la base. 

database/index.js

import { Database } from '@vuex-orm/core'
import User from '@/models/User'
import Todo from '@/models/Todo'

const database = new Database()

database.register(User)
database.register(Todo)

export default database

L'utilisation de Vuex-Orm dans notre application est indiquée dans le fichier index.js dans le dossier "store":

store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import VuexORM from '@vuex-orm/core'
import database from '@/database'

Vue.use(Vuex)

const store = new Vuex.Store({
  plugins: [VuexORM.install(database)]
})

export default store

Voilà ! Notre store Vuex est prêt à être utilisé ! En 4 fichiers d'à peine 15 lignes chacun, on a pu définir deux modèles de données avec des relations et implémenter Vuex dans toute notre application.

Utilisation du store

Maintenant que notre store est prêt à être utilisé, regardons du côté des composants comment manipuler nos données.

Le plugin présente nativement toutes les fonctions dont on a toujours besoin : insert(), update(),insertOrUpdate(), query(), delete() ... eh oui, vous verrez que nous n'avons plus besoin d'écrire toute la chaîne getters > actions > mutations > state car Vuex-ORM la prend déjà en charge !

Dans le dossier composant, vous trouverez le fichier App.vue, qui initialise jeu de données d'utilisateur avec la fonction .insert() qui va automatiquement ajouter les utilisateurs à notre state. Pour faire la même chose avec Vuex, nous aurions dû écrire toute la chaîne action > mutation > state pour récupérer une liste d'utilisateurs. Ici, c'est beaucoup de temps de gagné !

Si l'on regarde du côté de notre composant UserList.vue, du côté javascript, on peut voir qu'une première requête est effectuée à la "base" pour récupérer la liste d'utilisateurs : 

computed: {
    users () {
      return User.query().with('todos').orderBy('id', 'desc').get()
    }
  },

Et que le plugin gère tout aussi bien la modification et suppression d'entité !

methods: {
    update (user, name) {
      user.$update({ name })
    },

    destroy (user) {
      user.$delete()
    }
  }

Vuex-ORM prend en charge toutes les opérations CRUD que vous auriez dû écrire dans vos modules Vuex ! C'est à mon sens un énorme gain de temps et d'énergie car cela fait beaucoup moins de lignes de code à maintenir que si nous utilisions un store vuex "natif".

Qu'en pensez-vous ? 

J'espère que vous avez fait une belle découverte avec ce plugin et je vous dis à bientôt ! 

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus