2017-12-20 2 views
0

Beispiel des Problems: https://jsfiddle.net/hxv5bLqt/VueJS 2 - Uhr-Eigenschaften innerhalb Arrays und/oder Objekte

I haben eine Datenstruktur mit 2 Ebenen (Arrays). Die erste Ebene ist die "Teile" und die zweite Ebene sind die "Elemente", die in jedem "Teil" sind. Es gibt auch eine Variable, die den Gesamtwert der einzelnen Werte speichert. Das Beispiel funktioniert wie folgt: Jedes Mal, wenn der Benutzer etwas in ein Wertfeld eingibt oder einen Wert entfernt, muss die Summe neu berechnet werden.

Allerdings bin ich mit der Beispiellösung nicht zufrieden, da ich alle Stellen zuordnen muss, an denen die "this.recompute()" -Methode aufgerufen werden sollte, und dies mit Watch oder berechneten Eigenschaften klarer, sauberer und reaktiver gelöst.

Ich bin jedoch nicht in der Lage, eine "Überwachung" oder eine "berechnete Eigenschaft" zu implementieren, die Änderungen in den Eigenschaften von Objekten innerhalb von Arrays sehen kann.

Für die „watch“ Fall stelle ich mir vor, dass das Ideal und dem, was ich dachte, ist funktionieren würde:

watch: { 
    'parts.X.items.Y.value': function(oldValue, newValue) { 
     this.recompute() 
    } 
} 

Das „X“ und „Y“ Variablen angeben, die angeben, dass die Felder beobachtet werden wird in jeder Position der Arrays sein.

Auf diese Weise würde jedes Mal, wenn der Benutzer auf die Schaltfläche klickt, um ein Element zu entfernen, oder etwas in das Wertfeld eingegeben wurde, die Überwachung ausgelöst. Aber das funktioniert nicht.

Auf diese Weise würde jedes Mal, wenn der Benutzer auf die Schaltfläche klickt, um ein Element zu entfernen, oder etwas in das Wertfeld eingegeben wurde, die Überwachung ausgelöst. Dies gilt jedoch nicht funktioniert und ich bin verpflichtet, alle Punkte werden Abbildung, wo die „this.recompute()“ Methode aufgerufen werden soll, wie folgt:

onClickRemoveItem(event, part, item) { 
    ... 
    this.recompute() // RECOMPUTE HERE. 
}, 

onKeyupItemValue(event) { 
    this.recompute() // RECOMPUTE HERE. 
}, 

Ich denke, dies ist kein guter Weg, um das zu lösen Problem, weil, wenn es 10 weitere Orte gibt, wo die "this.recompute()" Methode aufgerufen werden sollte, es schwierig sein wird, sich an alle Rufstellen zu erinnern.

Es wäre eine Möglichkeit, dies auf eine elegantere Weise zu tun?

Antwort

0

Wenn Sie Ihre Summe zu einer berechneten Eigenschaft machen, erhalten Sie viel mehr freie Reaktivität (das heißt, Sie müssen nicht auf Aktualisierungen der Elementwerte warten oder explizit etwas neu berechnen). Sehen Sie hier die Antwort für spezifische Implementierung: https://jsfiddle.net/16wk9gre/

html

<script src="https://unpkg.com/vue"></script> 
<div id="app"> 
    <h3>Tests</h3> 
    <ul> 
    <li v-for="part in parts"> 
     <span>{{ part.name }}</span> 
     <ul> 
     <li v-for="item in part.items"> 
      R$ <input type="number" v-model="item.value"> 
      <button type="button" @click="onClickRemoveItem($event, part, item)">Remove</button> 
     </li> 
     <p> 
      Part subtotal: ${{ part.items.reduce((acc, item) => acc + parseFloat(item.value), 0) }} 
     </p> 
     <p> 
      Part subtotal (alternate): ${{ calculatePartSubtotal(part.items) }} 
     </p> 
     </ul> 
    </li> 
    </ul> 

    <p><strong>Total value:</strong>R$ {{ total }}</p> 
</div> 

JS

new Vue({ 
    el: '#app', 
    data() { 
    return { 
     // Define some nested mock data. 
     parts: [ 
     { id: 1, name: 'Part 1', items: [{ id: 1, value: 10.00 }, { id: 2, value: 5.00 }] }, 
     { id: 2, name: 'Part 2', items: [{ id: 3, value: 15.00 }] } 
     ] 
    } 
}, 
computed: { 
    total() { 
    let total = 0.0 
    for (let i = 0; i < this.parts.length; i++) { 
     for (let j = 0; j < this.parts[i].items.length;; j++) { 
     total += parseFloat(this.parts[i].items[j].value) 
     } 
    } 
    return total 
    } 
}, 
methods: { 
    calculatePartSubtotal (items) { 
    return items.reduce((acc, item) => acc + parseFloat(item.value), 0) 
    }, 
    // Remove an item of a part. 
    onClickRemoveItem(event, part, item) { 
    let index = part.items.findIndex(e => e.id === item.id) 
    this.$delete(part.items, index) 
    } 
} 
}) 
+0

Vielen Dank für Ihre Antwort @SciGuyMcQ, es wird eine Menge für "total" helfen, aber wenn ich es wollte Berechnen Sie 1 Summe für jedes Teil, wobei diese Summe eine Summe aller Artikelwerte dieses Teils ist? Wie kann ich in diesem Fall eine berechnete Eigenschaft deklarieren? –

+0

Ok, Sie können also den Eingabetyp in Zahl ändern und die Werte als Gleitkommawerte in einer Reduzierungsfunktion analysieren und eine Teilsumme pro Teil erhalten. Ich habe die Antwort und den JSFiddle bearbeitet. Sie könnten das auch zu einer Methode extrahieren und die part.items wie '{{calculatePartSubtotal (part.item)}}' ' – SciGuyMcQ

+0

Sinn jetzt? – SciGuyMcQ