8
votes

Alternatives de proxy JavaScript

Je veux utiliser proxy sur une classe personnalisée appelée observablier qui contient un tableau . Étant donné que proxy est disponible uniquement après ES6, je me demande s'il existe une mise en œuvre alternative.

Mon exigence est de se mettre à jour (plutôt que de vous faire remarquer) pour les observateurs une fois observabliste Les changements, de sorte que les observateurs sont toujours consistés à être observables avec une méthode de filtrage ou de mappage. xxx

mon implémentation avec proxy est disponible sur https://jsfiddle.net/ovilia/tlmbptr0/3/


5 commentaires

Est-ce activités.Push ou activités.list.push ?


Quels scénarios d'utilisation votre liste observable doit-elle travailler? Jusqu'à présent, vous n'avez fait que appeler une méthode push et attribuer à des indices déjà existants. De quoi d'autres avez-vous besoin? Soyez précis s'il vous plait.


@Bergi activités.list.push . J'ai besoin de toutes les opérations de tableau tels que push , shift , épissure et etc. à regarder.


Si tel est tout, vous n'avez même pas besoin de proxies - juste sous-classe tableau et écrasez chaque méthode de mise à jour avec celle qui appelle super puis notifie les observateurs.


@Bergi Array Indexiers et Longueur sont difficiles à élever avec cette approche. La réponse de Liuji-Jim est largement adoptée dans de nombreux cadres. C'est frustrant, mais travaille en quelque sorte. Ou chèque sale, comme angulaire, ennuyeux et laids ...


3 Réponses :


2
votes

utilisé defineProperty .

Pas exactement avec ce que vous voulez. Je viens de mettre en œuvre un "tableau réactif". Mais je pense que cela fonctionne peut-être dans vos problèmes.

Bad Pièces:

  1. Des tonnes définies de getters / setters sur la cible.
  2. Accès aux indexateurs non définis ne sera pas réactif.
  3. update () est à optimiser.

    bonnes parties:

    1. es5 sympathique.
    2. Si aucun indexeur n'est nécessaire, utilisez Set (i, Val) / get (i) sera réactif.

      https://jsfiddle.net/jimnox/jrtq40p7/2/


0 commentaires

0
votes

utilise des proxies une exigence difficile? Je ne recommanderais pas les proxy pour tâches de programmation générales comme vous pouvez vous retrouver avec imprévisible et effets secondaires difficiles à repérer.

Si vous gardez les données et les fonctions pour le transformer, évitez de l'être mutable état dans la mesure du possible, je pense que vous allez vous retrouver avec un code plus simple qui est plus facile à maintenir. p>

p>

var activities = ['reading', 'swimming'];

var sfilter = function(activities){
    return activities.filter(function(v){
        return v[0] === 's';
    });
};

console.log(sfilter(activities));

var memap = function(activities){
    return activities.map(function(v){
        return 'I am ' + v;
    });
};

console.log(memap(activities));

activities.push('smiling');
console.log(sfilter(activities));
console.log(memap(activities));

// Yes, I know this doesn't work in quite the same way,
// but you're asking for trouble here since in your
// code you're appending to one list, but overwriting
// an element in the other.
activities[1] = 'snoopying';
console.log(sfilter(activities));
console.log(memap(activities));


2 commentaires

Ceci est vraiment hors de suivi. L'OP a l'intention d'atteindre un Réactif paradigme de programmation qui est également compatible avec l'ES5. C'est pourquoi il / elle veut se débarrasser de proxy , qui est le cas d'utilisation parfaite (mais disponible uniquement après ES6). OMI cela ne serait pas et ne devrait pas être une logique d'entreprise. Cela ressemble plus à une exigence de niveau-cadre.


@Leo sûr. Je faisais remarquer sur l'idée de l'OP de mettre à jour des données en miroir plutôt que d'observer; Je n'ai pas fait ça clair.



0
votes

Comme décrit dans les questions, j'ai seulement besoin de observablelist code> à contenir em> un tableau code>, plutôt que pour étendre em> , comme Jim l'a fait dans sa réponse em> compliquée. Et étonnamment assez, j'ai trouvé que cela pourrait être facilement réalisé en enveloppant le tableau d'origine code> Opérations Strong>.

Une limitation est que Index n'est pas réactif fort > Dans ma mise en œuvre, je n'ai pas trouvé de moyen approprié de capturer des opérations d'index. Si vous avez une meilleure idée, sentez-vous la bienvenue pour me dire! XD P>

Voici toute la mise en œuvre complète. P>

export class ObservableList {

  list: Array<any>;

  private _observer: Array<ObserverList>;

  constructor(list?: Array<any>) {
    this.list = list || [];
    this._initList();
    this._initMethods();

    this._observer = [];
  }

  notify(): void {
    for (let o of this._observer) {
      o.update();
    }
  }

  private _initList(): void {
    var that = this;
    var operations = ['push', 'pop', 'shift', 'unshift', 'splice',
      'sort', 'reverse'];
    for (let operation of operations) {
      this.list[operation] = function() {
        var res = Array.prototype[operation].apply(that.list, arguments);
        that.notify();
        return res;
      }
    }
  }

  private _initMethods(): void {
    var that = this;
    var methods = ['filter', 'map'];
    for (let method of methods) {
      this[method] = (formatter: Function): ObserverList => {
        var observer = new ObserverList(that, formatter, method);
        this._observer.push(observer);
        return observer;
      }
    }
  }

}

export class ObserverList {

  public list: Array<any>;

  constructor(public observable: ObservableList, 
              public formatter: Function, 
              public method: string) {
    this.list = [];
    this.update();
  }

  update(): void {
    var list = [];
    var master = this.observable.list;
    for (var i = 0, len = master.length; i < len; ++i) {
      if (this.method === 'filter') {
        if (this.formatter(master[i])) {
          list.push(master[i]);
        }
      } else if (this.method === 'map') {
        list.push(this.formatter(master[i]));
      } else {
        console.error('Illegal method ' + this.method + '.');
      }
    }
    this.list = list;
  }

}


2 commentaires

Attendez une minute, c'est Thypscript, n'est-ce pas?


@Leo Oui, mais je ne pense pas que cela fait de différence, non?