🇫🇷 Un Proxy en JS, c'est bien pratique, la suite

Bonjour! Alors j'étais plutôt fier de mon dernier article et de mon début d'implémentation de modèle, jusqu'à ce que je trouve un bug (ou une fonctionnalité qui ne m'arrange pas 😉).

text

Donc si j'ajoute un buddy à Jack, (jack.buddy = new Buddy({avatar:"😃", firstName:"John", lastName:"Doe"})) il récupère la méthode change de Jack, alors que je voudrais que chaque modèle (chaque instance) puisse avoir sa propre méthode change.

On m'avait bien dit de pas jouer avec les portotypes (ce n'est peut-être même pas ça en fait) - J'ai essayé de modifier mon code, mais à l'heure actuelle, je n'ai pas trouvé de solution 😢.

Donc, pour le moment, ma conclusion est/serait:, ma 1ère implémentation est certainement intéressante, mais pas pour des modèles (notamment si j'ai des modèles de modèles - et nous n'avons pas encore parle des collections 🙀 - prochain article). Pourtant, je suis persuadé, que le Proxy est parfait pour ça.

J'ai donc réfléchi à une autre façon de faire, plus simple, mais qui devrait faire le job. Cette fois-ci, je suis parti sur une sorte de factory de modèles dans un esprit beaucoup plus "fonctionnel". Souhaitons que cela fonctionne 🤞.

👋 pour rappel, je suis toujours preneur bien sûr d'autres solutions, remarques, etc...

🎉 Nouvelle version de mes modèles

Voici donc mon nouveau code:

function Model(options) {
  let structure = Object.assign({
    on: function(eventName, handler) {
      this[eventName]=handler
    }
  }, options)
  return new Proxy(structure, {
    get: function (target, property) {
      return target[property]
    },
    set: function (target, property, value) {
      target[property] = value
      if (target.change) target.change(target, property)
      return true
    }
  })
}

👋 donc ce code remplace celui du précédent modèle

Et je l'utiliserais comme ceci (par exemple):

let jack = Model({avatar:"🎃", firstName:"Jack", lastName:"O'Lantern"})

jack.on("change", (model, property) => {
  johnDoeComponent.setAttribute(property, model[property])
  johnDoeComponent.render() 
})

La démo! La démo! La démo!

Avant la démonstration, je vais aller ajouter un 2ème web component pour pouvoir afficher les informations du "buddy":

<my-buddy 
  id="john-doe"
  avatar="😎"   
  firstName="???" 
  lastName="???">
</my-buddy>

<my-buddy 
  id="john-doe-s-buddy"
  avatar="😃"   
  firstName="???" 
  lastName="???">
</my-buddy>

Je sauvegarde et j'ouvre ma page:

text

Donc cela correspond plus à mon cahier des charges 😃

Avant de partir: si je devais "encapsuler" dans une classe

J'aime quand même bien les classes en JavaScript, car ça peut aider à la lisibilité, modularité, bla bla bla ... J'ai donc une autre version en parallèle qui est juste "esthétique" (les goûts et les couleurs ...), souvenez vous, au début de l'article, je parlais de factory:

class Model {
  static of(options) {
    let structure = Object.assign({
      on: function(eventName, handler) {
        this[eventName]=handler
      }
    }, options)
    return new Proxy(structure, {
      get: function (target, property) {
        return target[property]
      },
      set: function (target, property, value) {
        target[property] = value
        if (target.change) target.change(target, property)
        return true
      }
    })
  }
}

Et je l'utiliserais comme ceci (moi je trouve que c'est plus joli 🌺):

let jack = Model.of({avatar:"🎃", firstName:"Jack", lastName:"O'Lantern"})

Voilà, c'est tout pour aujourd'hui. Je vais continuer à jouer avec, et si ça répond à mes attentes, je vous écris quelque chose sur les collections, et je mets tout ça sous forme de framework (librairie plutôt).

Passez tous une bonne journée.

Last Articles

Last Updated: 07/01/2020 à 06:49:53