@tracked Der Zustand eines Arrays oder Objekts innerhalb einer Glimmer-Komponente löst keine Updates aus, wenn Sie ein Element des Arrays/Objekts ändern.
Dieses Thema behandelt einige Optionen, damit Ihre Ansicht ordnungsgemäß aktualisiert wird. Ich wollte eine weitere Methode hinzufügen, da die dort besprochenen Optionen für mich nicht funktionierten.
So habe ich das gelöst: Anstatt ein Element nach dem anderen zuzuweisen, weisen Sie das gesamte Array auf einmal zu. Diese gleiche Strategie würde auch mit einem Objekt oder einer anderen Datenstruktur funktionieren.
In einer Glimmer-Komponente:
@tracked categories = [];
constructor() {
super(...arguments);
this.loadAllData();
}
async loadAllData() {
const categories = []
const waiting = this.siteSettings.county_fence_print_categories.split('|').map(async (cid, index) => {
const data = await this.loadData(`/c/${cid}/l/latest.json?period=monthly`)
return data.topic_list.topics
})
// DAS IST DIE ZEILE, AUF DIE SIE ACHTEN SOLLTEN
// Da wir = direkt dem Array zuweisen, wird ein Update ausgelöst.
// Hingegen würden das Hinzufügen zum Array oder das Setzen von Elementen nach Index kein Update auslösen.
this.categories = await Promise.all(waiting)
}
async loadData(url) {
try {
const data = await ajax(url);
//console.log(`Got data for ${url}:`, data)
return data
} catch (error) {
console.error(`Failed to get data for ${url}:`, error);
}
}
Sie könnten dies auch mit einem teilweisen Update tun. Wichtig ist, dass JavaScript erkennt, dass ein anderer Wert zugewiesen wird. Während .concat also funktioniert, da es ein neues Array erzeugt, das sich vom alten unterscheidet:
this.categories = this.categories.concat(newValue)
Die Verwendung von .push wird wahrscheinlich nicht funktionieren, da das resultierende Array die gleiche Objekt-ID wie das Original hat, sodass JavaScript denkt, dass sich nichts geändert hat.
this.categories.push(newValue)
this.categories = this.categories
Wenn Sie mit einem Objekt arbeiten, ist eine einfache Möglichkeit, ein neues zu erstellen, Object.assign() - das eine neue, erweiterte Datenstruktur erstellt, ähnlich wie .concat oben.
Dies ist seit langem auch bei anderen Frameworks wie Vue.js der Fall – Sie finden Themen dazu, die 10 Jahre zurückreichen. Es hat mit der Art und Weise zu tun, wie es in JavaScript implementiert ist, wahrscheinlich entweder mit Gettern/Settern im übergeordneten Objekt oder der observe-API. Aber wenn es mit der observe-API implementiert ist, gibt es weniger Entschuldigung für dieses Verhalten, da es einfach wäre, das Subtree-Flag zu aktivieren… Vielleicht haben sie sich aus Performancegründen dagegen entschieden, wenn sie eine tief verschachtelte Struktur beobachten? Aber ich schweife ab, das sind Implementierungsdetails der zugrunde liegenden Bibliotheken. Der obige Workaround sollte Ihnen helfen, damit umzugehen.