2015-05-08 17 views
24

Declinazione di responsabilità: Questo è il mio primo tentativo di creare un'app MVVM Anche in precedenza non ho lavorato con vue.js, quindi potrebbe essere che il mio problema sia il risultato di un problema più fondamentale .Vue JS Guardare oggetti nidificati profondi


Ritengo ho due tipi di blocchi con caselle:

  • Tipo 1: blocco/caselle
  • tipo 2: blocco/intestazioni/checkboxes

Il sottostante oggetto è strutturato in questo modo:

{ 
    "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 
      } 
      ] 
     } 
     ] 
    } 
    ] 
} 

miei obiettivi

caselle Selezione:

  1. utente fa clic su casella di controllo, casella di controllo è selezionata (selezionato = true)
  2. Metodo è sparato per controllare se tutte le altre caselle di controllo devono essere disabilitato (disabilitato = true). (Se questo metodo ha infatti disattivato qualsiasi cosa, si chiede anche di nuovo, perché altri elementi potrebbero essere a sua volta dipende dal elemento disattivato)
  3. Un altro metodo aggiorna alcune altre cose, come le icone ecc

caselle di controllo Cancellazione

Un utente può fare clic su un pulsante "Cancella", che deseleziona tutte le caselle di controllo in un elenco (selezionato = falso). Questa azione dovrebbe anche innescare i metodi che disattiva opzionalmente caselle di controllo e aggiorna le icone ecc

Il mio metodo attuale(che non sembra giusto)

  • L'attributo selezionato del dati- il modello è associato allo stato selezionato dell'elemento checkbox tramite la direttiva v-model.
  • L'attributo disabilitato (dal modello) è associato alla classe dell'elemento e all'attributo disabilitato. Questo stato è impostato dal metodo sopra menzionato.
  • Per inizializzare i metodi che disattivano le caselle di controllo e modificano alcune icone, sto usando una direttiva v-on="change: checkboxChange(this)". Penso che ho bisogno di fare questa parte in modo diverso metodo
  • Il clearList si chiama via v-on="click: clearList(this)"

I problemi con la mia messa a punto corrente è che l'evento cambiamento non sta sparando quando le caselle di controllo vengono cancellati programatically (vale a dire non per interazione dell'utente).

Quello che vorrei invece
Per me la cosa più logica da fare sarebbe quella di utilizzare this.$watch e tenere traccia delle modifiche nel modello, invece di ascoltare per gli eventi DOM.

Una volta apportato un cambiamento, dovrei quindi identificare quale oggetto esatto è cambiato e agire di conseguenza. Ho provato a creare una funzione $watch che osserva l'array blocks. Questo sembra raccogliere bene le modifiche, ma restituisce l'intero oggetto, a differenza dell'attributo individuale che è cambiato. Inoltre a questo oggetto mancano alcuni utili attributi di supporto, come $parent.

Posso pensare ad alcuni metodi hacky per far funzionare l'app (come ad esempio l'attivazione manuale degli eventi di modifica nel metodo clearList, ecc.) Ma il mio caso d'uso sembra piuttosto standard, quindi mi aspetto che ci sia probabilmente un modo molto più elegante di gestire questo.

risposta

7

Poiché nessuno ha risposto e ho risolto/risolto il problema, ho pensato che sarebbe stato utile pubblicare la mia soluzione. Si prega di notare che non sono sicuro che la mia soluzione sia come affrontare questi tipi di cose, funziona comunque.

Invece di utilizzare questo listener di eventi v-on="change: checkboxChange(this)" Attualmente sto utilizzando una direttiva personalizzata che ascolta sia l'attributo del modello selezionato che quello disabilitato, come questo: v-on-filter-change="selected, disabled".

La direttiva si presenta così:

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 
    } 
}, 

La clausola if sembra un po 'hacky, ma non riuscivo a trovare un altro modo. Almeno funziona tutto.

Forse questo sarà utile a qualcuno in futuro.

55

è possibile utilizzare il metodo 'orologio' .. per esempio se i dati sono:

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

Si potrebbe fare qualcosa di simile:

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

. Selected e .disabled sono proprietà di oggetti variabili anonimi che appartengono all'array delle variabili. Il tuo esempio funziona perché è solo un singolo oggetto non un array. – Hendrik

+0

Ho fatto qualcosa come block.checkbox.active, ma non funziona finché non li aggiungo in "" come accennato sopra. Grazie. Ora funziona. –

5

Se si desidera vedere l'oggetto come un intero con tutte le sue proprietà, e non solo solo una proprietà, si può fare questo, invece:

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

preavviso 0.123.e deep: true

+0

Grazie per questo. Tuttavia, poiché la mia domanda ha più di due anni e da allora non uso Vue, non posso verificare se funzioni. – Hendrik

+1

@ Hendrik non preoccuparti, spero che questo aiuti qualcuno che ha lo stesso problema – peerbolte

+0

Sai cosa dovrei fare se volessi solo vedere "prop1'? –

2

Altre soluzioni non menzionate qui: Utilizzare l'opzione deep.

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