2015-05-08 13 views
24

Disclaimer: Dies ist mein erster Versuch eine MVVM App zu erstellen Ich habe auch noch nicht mit vue.js gearbeitet, also könnte es gut sein, dass mein Problem das Ergebnis eines grundlegenderen Problems ist .Vue JS Zusehen tief verschachteltes Objekt


Aus meiner Sicht Ich habe zwei Arten von Blöcken mit Kontrollkästchen:

  • Typ 1: Block/Kontrollkästchen
  • Typ 2: Block/Header/Ankreuzfelder

Die zugrunde liegenden Das Objekt ist folgendermaßen aufgebaut:

{ 
    "someTopLevelSetting": "someValue", 
    "blocks": [ 
    { 
     "name": "someBlockName", 
     "categryLevel": "false", 
     "variables": [ 
     { 
      "name": "someVarName", 
      "value": "someVarValue", 
      "selected": false, 
      "disabled": false 
     } 
     ] 
    }, 
    { 
     "name": "someOtherBlockName", 
     "categryLevel": "true", 
     "variables": [ 
     { 
      "name": "someVarName", 
      "value": "someVarValue", 
      "categories": [ 
      { 
       "name": "SomeCatName", 
       "value": "someCatValue", 
       "selected": false, 
       "disabled": false 
      } 
      ] 
     } 
     ] 
    } 
    ] 
} 

Meine Ziele

Auswahl Kontrollkästchen: wenn alle anderen Kontrollkästchen

  1. Nutzer klickt auf eine Checkbox, wird Kontrollkästchen aktiviert (ausgewählt = true)
  2. Verfahren überprüfen gebrannt sein müssen deaktiviert (deaktiviert = wahr). (Wenn diese Methode in der Tat etwas deaktiviert hat, es nennt sich auch wieder, weil andere Elemente wiederum abhängig von der deaktivierte Element sein könnte)
  3. Eine andere Methode aktualisiert einige andere Dinge, wie Symbole usw.

Clearing-Kontrollkästchen

Ein Benutzer kann auf eine Schaltfläche "Löschen" klicken, die alle Kontrollkästchen in einer Liste deaktiviert (ausgewählt = false). Diese Aktion sollte auch die Methoden auslösen, usw. Kontrollkästchen und Updates Symbole optional

Meine aktuelle Methode(was ganz richtig scheint nicht)

  • Das ausgewählte Attribut des Daten- deaktiviert Das Modell ist an den überprüften Status des Kontrollkästchenelements über die v-model-Direktive gebunden.
  • Das deaktivierte Attribut (aus dem Modell) ist an die Klasse und das deaktivierte Attribut des Elements gebunden. Dieser Zustand wird durch die vorgenannte Methode eingestellt.
  • Um die Methoden zu initialisieren, die Kontrollkästchen deaktivieren und einige Symbole ändern, verwende ich eine v-on="change: checkboxChange(this)" Direktive. Ich glaube, ich brauche diesen Teil anders
  • Die Clear tun Methode über v-on="click: clearList(this)"

Die Probleme mit meinem aktuellen Setup aufgerufen wird, ist, dass das Ereignis Änderung nicht ausgelöst wird, wenn die Kontrollkästchen programmatisch gelöscht (dh nicht durch Benutzerinteraktion).

Was würde Ich mag stattdessen
Für mich ist die logischste Sache zu tun wäre, this.$watch zu verwenden und in der Modellbahn von Änderungen zu halten, anstatt für DOM-Ereignisse zu hören.

Sobald es eine Änderung gibt, würde ich dann identifizieren müssen, welches genaues Element geändert wurde, und darauf handeln. Ich habe versucht, eine $watch Funktion zu erstellen, die das blocks Array beobachtet. Dies scheint die Änderungen in Ordnung zu bringen, aber es gibt das vollständige Objekt zurück, im Gegensatz zu dem einzelnen Attribut, das sich geändert hat. Auch diesem Objekt fehlen einige praktische Helferattribute wie $parent.

Ich kann mir einige hacky Wege vorstellen, um die App funktionieren zu lassen (z. B. manuelle Auslösung von Änderungsereignissen in meiner ClearList-Methode, etc.), aber mein Anwendungsfall scheint ziemlich Standard, also erwarte ich wahrscheinlich einen viel eleganteren Weg geh damit um.

Antwort

7

Da niemand geantwortet hat und ich das Problem inzwischen gelöst/bearbeitet habe, dachte ich, es wäre nützlich, meine Lösung zu posten. Bitte beachten Sie, dass ich nicht sicher bin, ob meine Lösung ist, wie diese Art von Dingen angegangen werden sollte, aber es funktioniert.

Statt dieses Ereignis-Listener verwenden v-on="change: checkboxChange(this)" Ich verwende jetzt eine benutzerdefinierte Richtlinie, die das ausgewählte und behinderte Modell Attribut sowohl zuhört, wie folgt aus: v-on-filter-change="selected, disabled".

Die Richtlinie sieht wie folgt aus:

directives: { 
    'on-filter-change': function(newVal, oldVal) { 
     // When the input elements are first rendered, the on-filter-change directive is called as well, 
     // but I only want stuff to happen when a user does someting, so I return when there is no valid old value 
     if (typeof oldVal === 'undefined') { 
      return false; 
     } 
     // Do stuff here 
     // this.vm is a handy attribute that contains some vue instance information as well as the current object 
     // this.expression is another useful attribute with which you can assess which event has taken place 
    } 
}, 

Die if-Klausel ein bisschen hacky scheint, aber ich konnte einen anderen Weg nicht finden. Zumindest funktioniert alles.

Vielleicht wird dies für jemanden in der Zukunft nützlich sein.

55

Sie könnten die ‚Uhr‘ Methode .. beispielsweise verwenden, wenn Sie Ihre Daten:

data: { 
    block: { 
     checkbox: { 
      active:false 
     }, 
     someotherprop: { 
      changeme: 0 
     } 
    } 
} 

Sie so etwas tun könnte:

data: {...}, 
watch: { 
    'block.checkbox.active': function() { 
     // checkbox active state has changed 
     this.block.someotherprop.changeme = 5; 
    } 
} 
+1

.selected und .disabled sind Eigenschaften von anonymen Variablenobjekten, die zum Variablenarray gehören. Ihr Beispiel funktioniert, weil es nur ein einzelnes Objekt und kein Array ist. – Hendrik

+0

Ich habe etwas wie block.checkbox.active, aber es funktioniert nicht, bis ich sie in "" wie Sie oben erwähnt hinzufügen. Vielen Dank. Es funktioniert jetzt. –

5

Wenn Sie das Objekt sehen möchten, wie ein Ganzes mit all seinen Eigenschaften, und nicht nur eine nur Eigenschaft, können Sie diese stattdessen tun:

data() { 
    return { 
     object: { 
      prop1: "a", 
      prop2: "b", 
     }  
    } 
}, 
watch: { 
    object: { 
     handler(newVal, oldVal) { 
      // do something with the object 
     }, 
     deep: true, 
    }, 
}, 

Hinweis und deep: true

+0

Danke dafür. Da meine Frage jedoch über zwei Jahre alt ist und ich Vue seitdem nicht verwendet habe, kann ich nicht überprüfen, ob das funktioniert. – Hendrik

+1

@Hendrik keine Sorgen, ich hoffe, das hilft jemandem, der das gleiche Problem hat – peerbolte

+0

Wissen Sie, was ich tun soll, wenn ich nur 'prop1' sehen will? –

2

Andere Lösung, die hier nicht erwähnt wird: Verwenden Sie die Option deep.

watch:{ 
    block: { 
    handler: function() {console.log("changed") }, 
    deep: true 
    } 
}