Vue: Unterstützen Sie mehr Sammlungsdatentypen in v-for

Erstellt am 28. Feb. 2016  ·  39Kommentare  ·  Quelle: vuejs/vue

In manchen Situationen ist ein einfaches Objekt nicht die beste Wahl. Ich habe versucht, ein Map -Objekt mit v-for zu rendern, aber es scheint, dass Vue es derzeit nicht unterstützt. (Hier ist ein Beitrag, den ich im Hilfethread des Forums erstellt habe.)

Ich hoffe, Vue kann die Syntax for ... of in v-for bereitstellen, um über Datentypen wie Map und Set zu iterieren.

Beispielsweise:

const map = new Map();
map.set('key1', 'val1');
map.set('key2', 'val2');

und wir können map auf diese Weise rendern:

<ul>
    <li v-for="[key, val] of map">{{key}} - {{val}}</li>
</ul>
feature request

Hilfreichster Kommentar

Es ist wichtig, Iteratoren in Schleifen durchlaufen zu können. Das scheint offensichtlich. Es ist ein grundlegendes Merkmal der Sprache.

Die Gründe für die Unterstützung sind:

1) Iteratoren, Maps und Sets sind alle gültiges ES6. Wenn Sie sich weigern, sie zu unterstützen, müssen Sie sich auf ES5 beschränken, eine Entscheidung, die mit der Zeit immer weniger gerechtfertigt ist.
2) Ich baue eine Anwendung mit internen Daten, die in Maps und Sets gespeichert sind. Anstatt sie der Benutzeroberfläche zur Verfügung zu stellen, muss ich jetzt die Daten zwischen den beiden manuell synchronisieren oder Boilerplate schreiben und in meine Vorlagen importieren, um die Konvertierung durchzuführen, wann immer die Daten benötigt werden. Genau das soll Vue vermeiden.

Alle 39 Kommentare

Ein Duplikat von https://github.com/vuejs/vue/issues/1319

@wenLiangcan , Sie könnten so etwas verwenden:

<ul>
    <li v-for="[key, val] of get(map)">{{key}} - {{val}}</li>
</ul>

wobei get() Ihre Funktion ist.

Haha! ähnliche Probleme sind die ganze Zeit offen und die Leute bestehen darauf, dass sie die Implementierung nicht rechtfertigen können gut die Leute wollen es verwenden das ist eine Rechtfertigung Ich kann auch die Bazillion der geschlossenen Probleme auflisten, die dasselbe verlangen xD. Ich habe auch einen gefunden, der den Anwendungsfall wirklich gut begründet und sich auf die es6-Spezifikation bezieht, wenn es um die Kartenreihenfolge geht -> noch geschlossen.

Personen, die eine Funktion verwenden möchten, sind nicht allein ein Argument, das die Notwendigkeit einer solchen Funktion rechtfertigen kann

Ja, aber die Argumente, die Leute verwenden, um das Problem zu schließen, sind immer noch nicht gültig oder zumindest nicht für alle Anwendungsfälle gültig, zB das Beispiel des Elipen, der seine Anwendungsfälle sehr gut begründet hat, wie ich oben erwähnt habe

Wenn Sie ein bestimmtes Thema besprechen möchten, verlinken Sie es bitte.

Außerdem ist dieses Feature-Problem offen. Es ist nicht sinnvoll, für dieselbe Anfrage mehr als ein Problem zu öffnen.

Es ist wichtig, Iteratoren in Schleifen durchlaufen zu können. Das scheint offensichtlich. Es ist ein grundlegendes Merkmal der Sprache.

Die Gründe für die Unterstützung sind:

1) Iteratoren, Maps und Sets sind alle gültiges ES6. Wenn Sie sich weigern, sie zu unterstützen, müssen Sie sich auf ES5 beschränken, eine Entscheidung, die mit der Zeit immer weniger gerechtfertigt ist.
2) Ich baue eine Anwendung mit internen Daten, die in Maps und Sets gespeichert sind. Anstatt sie der Benutzeroberfläche zur Verfügung zu stellen, muss ich jetzt die Daten zwischen den beiden manuell synchronisieren oder Boilerplate schreiben und in meine Vorlagen importieren, um die Konvertierung durchzuführen, wann immer die Daten benötigt werden. Genau das soll Vue vermeiden.

Da #1319 geschlossen ist, lohnt es sich, die aktuelle Entscheidung hier zu wiederholen. Kurz gesagt, die Implementierung der Funktion ist nicht trivial (auf der Ebene des Beobachtungsmechanismus), es geht also nicht darum, Anwendungsfälle zu rechtfertigen, sondern um den Arbeitsaufwand und die Kompromisse.

Ich würde mich auch sehr über diese Funktion freuen. Auf der anderen Seite, wenn die Beobachtung von ES6-Datentypen schrecklich hackig wird oder beispielsweise die Leistung oder andere Qualitäten beeinträchtigt, dann werden Leute, die Karten und Sets derzeit nicht mit Vue verwenden, diese Änderung möglicherweise nicht zu schätzen wissen.

Ich nehme an, die Verwendung von Array.from() innerhalb einer berechneten Funktion muss im

Irgendeine Lösung dafür?

Kleines Update, dies wird kommen, wenn / wenn Vue beschließt, "alte" Browser zu verwerfen und zu Evergreen-Browsern mit Proxy anstelle von set / get für Reaktivität zu wechseln.

@alexsandro-xpt, verwenden Sie einfach eine berechnete Funktion, die Array.from(yourDataSet) zurückgibt.

@nickmessing Ich versuche es mit Map, funktioniert nicht.
Der berechnete Array-Längenwert ist immer 0.

Nur Array.from ist wahrscheinlich keine Lösung, die Sie wegen mangelnder Reaktionsfähigkeit wünschen (Änderungen an yourDataSet werden nicht an Vue weitergegeben).

Wie bereits erwähnt, können Sets und Maps von Vue nicht beobachtet werden. Um diese zu verwenden – entweder in v-for oder in berechneten Eigenschaften, Methoden, Watchern, Vorlagenausdrücken usw. – müssen Sie eine serialisierbare Replik dieser Struktur erstellen und sie Vue zur Verfügung stellen. Hier ist ein naives Beispiel, das einen einfachen Zähler verwendet, um Vue mit Informationen zu versorgen, dass Set aktualisiert wird:

data() {
  mySetChangeTracker: 1,
  mySet: new Set(),
},

computed: {
  mySetAsList() { 
    // By using `mySetChangeTracker` we tell Vue that this property depends on it,
    // so it gets re-evaluated whenever `mySetChangeTracker` changes
    return this.mySetChangeTracker && Array.from(this.mySet);
  },
},

methods: {
  add(item) {
    this.mySet.add(item);
    // Trigger Vue updates
    this.mySetChangeTracker += 1;
  }
}

Dies veranschaulicht eine etwas hackige, aber zu 100% funktionierende Methode, um nicht beobachtbare Daten reaktiv zu machen. In realen Fällen landete ich jedoch bei serialisierten Versionen von Sets/Maps (zB möchten Sie wahrscheinlich die modifizierten Versionen von Sets/Maps in localstorage speichern und sie somit sowieso serialisieren), also waren keine künstlichen Zähler/Hacks beteiligt.

Ich persönlich denke, dass dies eine faire Lösung für ein Problem ist, aber es verdient definitiv eine offizielle Dokumentation – ansonsten ist es unmöglich, dies als nicht hackige Art und Weise zu rechtfertigen, mit Vue-Interna umzugehen.

@alexsandro-xpt, sorry, ich habe mich geirrt, die Berechnung wird hackig sein, wie @inca sagte, eine andere hackige Lösung wäre die Verwendung von $forceUpdate mit einer Methode, hier ist ein Beispiel für eine Geige

Danke @nickmessing und @inca , das funktioniert gut mit meinem new Map() !!

Wenn Sie jetzt ein "v-for" über einer "Map" ausführen, verhält sich das v-for, als ob es ein leeres Array erhalten hätte.

Unabhängig vom Ergebnis der ausführlichen Diskussion darüber, ob/wie Karten und Sets unterstützt werden sollen, würde es vielen Leuten viel Zeit bei der Fehlersuche sparen, wenn Vue einfach warnen würde: "Karten und Sets werden noch nicht unterstützt - siehe https://github .com/vuejs/vue/issues/2410 ".

Ja, die Google-Suche nach dieser Funktion hat mich zu diesem Ticket geführt (nach einigen nervigen Verwechslungen mit Vue.set)

👍 Das sollte in der v-for-Dokumentation stehen!

Sollte wirklich in V-für Dokumentation sein!

/cc @chrisvfritz lasst uns versuchen, einen Hinweis zur Unterstützung für diese Typen in den Dokumenten für v-for (sowohl API als auch der Abschnitt zum Listen-Rendering) hinzuzufügen - ich werde sie mir auch in 2.5 ansehen.

@yyx990803 Ich frage mich, ob eine Konsolenwarnung dafür besser wäre, da dies den Leuten sofort mitteilen würde, was falsch ist, und die Notwendigkeit entfällt, nach der Lösung zu suchen.

Wir haben in den Dokumenten auch schon sehr deutlich gemacht, welche Typen wir _unterstützen_, Map und Set nicht dazu. Ich kann definitiv das Argument dafür sehen, warum man _hoffen_ könnte, dass alle Iterables mit v-for funktionieren würden, aber ich glaube nicht, dass wir den Lesern derzeit einen Grund zu der Annahme geben, dass sie dies tun würden.

Ich sehe das Argument gegen das Hinzufügen von Unterstützung für Set nicht ganz.

Set selbst kann sauber mehrfach gefüllt werden, und wenn ich nichts übersehe, scheint es, als ob Vues Ansatz zum Hinzufügen von Reaktivität zu Arrays sehr leicht auf Mengen ausgedehnt werden könnte. Wir müssten nur .add() , .clear() und .delete() .

Meine beste Vermutung (bitte korrigieren/entschuldigen Sie, wenn ich falsch liege): Der schwierigste Teil besteht darin, einen Set Konstruktor zu umschließen, der ein Iterable akzeptiert. Ich sehe nicht, wie iterierbar beobachtbar gemacht werden kann, da es in seiner allgemeinen Form nur eine Funktion (dh next ) ohne referenzierbaren Zustand ist (denken Sie an einen generatorbasierten Iterator als Beispiel).

Warum müssen wir den Konstruktor umschließen? Würden wir nicht bereits vorhandene Sets an Vue übergeben?

Gemäß der Spezifikation durchläuft der Set Konstruktor sofort den gesamten Iterator und behält effektiv eine flache Kopie der vom Iterator zurückgegebenen eindeutigen Elemente bei. Sobald Sie eine Set Instanz haben, sollte es egal sein, ob sie von einem Iterator erstellt wurde oder nicht.

In dieser Hinsicht sollte sich ein Set das aus einem Iterator erstellt wurde, nicht von einem Array unterscheiden, das aus einem Iterator erstellt wurde (über Array.from() ), den Vue bereits unterstützt.

Sie können unveränderliche Maps/Sets/jegliche Datenstrukturen verwenden und eine Reaktivität mit ihnen zulassen, aber einfach, weil sich die gesamte Chunk-Referenz ändert. Sie können sie über eine Renderfunktion oder ein berechnetes generiertes Array rendern (das frühere hat eine bessere Leistung, da es die Erstellung eines Arrays überspringt..). Aber veränderliche Datenstrukturen, nicht so, es sei denn, Sie finden eine Möglichkeit, Vue manuell über bestimmte Änderungen zu benachrichtigen, was einfach eine eigene Lösung wäre.

Das ist nicht gut. Du kannst es nicht tun

@wenLiangcan

var map = new Map()
  map.set('key1','Test1')
  map.set('key2','Test2')
        <div class="file-size">{{value}}</div>
 </div>

Nein, es wird nicht auf der Seite angezeigt

Ich möchte das gerne unterstützen :)

Mich auch

Gibt es zukünftige Pläne, Support hinzuzufügen? Gibt es einen technischen Grund dafür, dass Vue Map und Set nicht unterstützen konnte?

Das aktuelle Problem mit der Vue.set-Methode für ein einfaches Objekt besteht darin, dass viel zu viele Abonnenten ausgelöst werden, wenn dem Objekt eine Eigenschaft hinzugefügt wird. Tatsächlich werden alle Abonnenten aller Eigenschaften ausgelöst, wenn nur eine Eigenschaft hinzugefügt wird.

Die Leistung der Ansicht wird stark beeinträchtigt, wenn eine kartenähnliche Sammlung Hundertstel von Schlüsseln enthält. In meinem Projekt werden beispielsweise Tausende von Abonnenten ausgelöst, wenn ein Element mit der Vue.set-Operation zur Karte hinzugefügt wird:

Vue.set(state.items, itemId, item); // where items is a plain object.

Wenn ich mir den Code von Vue.js genau anschaue, kann ich sehen, woher das Problem kommt. Die Abhängigkeiten, die ausgelöst werden, sind die des Objekts, dh wenn das Objekt eine Eigenschaft für jeden Schlüssel hat, werden alle Abhängigkeiten aller Schlüssel ausgelöst, wenn nur ein Schlüssel hinzugefügt wird.

Die Verwendung von einfachen Objekten zur Nachahmung einer Karte scheint daher nicht die richtige Lösung zu sein, und daher ist die Unterstützung einer Karte in vue für große Sammlungen von Elementen mehr als willkommen.

Gibt es Neuigkeiten zu zukünftigen Plänen und möglicherweise zum nativen Map/Set Support?

In diesem Artikel wird die bevorstehende Unterstützung in 2.6 beschrieben - aber in der offiziellen Roadmap steht nichts darüber, wie ich sehe?

https://medium.com/@alberto.park/the -status-of-javascript-libraries-frameworks-2018-beyond-3a5a7cae7513

"Der aktuelle neueste Kern ist 2.5.x. Die nächste Nebenversion (v2.6) wird den nativen ESM-Import, eine verbesserte asynchrone Fehlerbehandlung, einen Iterator für die 'v-for'-Direktive und mehr unterstützen."

Sie sind sich nicht sicher, woher sie diese Informationen haben?

Habe dieses Problem beim Debuggen des Verhaltens von Vue über Set Datenobjekte gefunden. :Denken:

Für Leute wie mich, die sich über die Roadmap dafür gewundert haben, sagt Evan You in diesem Video, dass die Unterstützung für Karten und Sets "wahrscheinlich" in 2.6 eintreffen wird, aber das war im Mai, also das ist alles, was ich weiß.

@yyx990803 Es ist bedauerlich, dass dieses Problem im Tracker als geschlossen gekennzeichnet ist, insbesondere wenn Sie erwägen, in naher Zukunft Unterstützung hinzuzufügen. Wo können wir den Fortschritt bei dieser Funktion verfolgen? Gibt es irgendwo noch ein Problem?

Ich frage mich nur, um der Argumentation willen, und vielleicht mache ich es falsch, aber da Sie die Array-Mutation mit den Mutation Methods verfolgen können, können Sie nicht einfach ein Array eines Objekts verfolgen und logisch vollständig sein? Sie erhalten nicht alle Funktionen, die in Map implementiert sind, aber die gewünschten Funktionen können ziemlich einfach angesprochen werden, insbesondere wenn Sie etwas wie _ oder lodash verwenden.

Es ist traurig, aber bis das Team dies hinzufügt, müssen wir möglicherweise alternative Datenstrukturen verwenden

Ich möchte nur einläuten, dass wir eine Karte für unsere Datenstruktur verwenden wollten, uns dann aber aufgrund fehlender Erstanbieterunterstützung dagegen entschieden haben.

wird dies jetzt in Vue3 unterstützt (d. h. reaktive Map und Set )?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen