Modello di caricamento dei dati per knockoutjs
-
27-10-2019 - |
Domanda
Sto cercando di capire se Knockoutjs funzionerà per la mia applicazione. Il mio modello di dati (semplificato) è il seguente:
function topic(data) {
this.id = data.id;
this.queries = ko.observableArray([]);
}
function query(data) {
this.id = data.id;
this.text = data.text;
this.searcher = data.searcherId;
this.postings = ko.observableArray([]);
}
function posting(data, query) {
this.documentId = data.docid;
this.rank = data.rank;
this.snippet = data.snippet;
this.score = data.score;
this.query = query;
this.document = null;
}
function document(data, topic) {
this.id = data.id;
this.url = data.url;
this.topic = topic;
}
Per una data topic
, Ne ho uno o più query
istanze. Ogni query contiene un elenco di posting
istanze. A testa posting
si riferisce a un documento. Più di una posting
può fare riferimento a un dato document
Finché il posting
Le istanze appartengono a diverse query
istanze.
Se una posting
si riferisce a un nuovo documento (uno non ancora recuperato da nessuno query
) Vorrei creare una nuova istanza; se la document
Esistono già (gli ID sono univoci), vorrei riutilizzarlo.
Riesco a vedere alcune possibili alternative per la strutturazione dei dati JSON restituiti dal server:
- Quando serializza le pubblicazioni, prima serializza un elenco di tutti i documenti e aggiorna l'elenco dei documenti principali con loro. Quindi, inviare post con riferimenti agli ID documenti.
- Serializzare ogni documento completamente come proprietà di una pubblicazione e quindi capire se quella voce è ridondante. Aggiungi voci non ridondanti all'elenco principale.
Qual è un modello ragionevole per la serializzazione dei dati? C'è qualche magia del plug -in di mappatura che lo esprimerebbe succintamente? Ho il controllo sul server che sta generando il JSON e posso strutturarlo in qualsiasi modo ha senso.
Grazie,
Gene
Soluzione
Ecco cosa ho finito per implementare l'opzione 1:
function idField(data) {
return ko.utils.unwrapObservable(data.id);
}
function createMapping(type, context) {
return {
key: idField,
create: constructor(type, context)
}
}
function constructor(type, context) {
return function(options) {
return new type(options.data, context);
}
}
function createReferenceMapping(collection) {
return {
key: idField,
create: lookup(collection)
}
}
function lookup(collectionOrClosure) {
return function(options) {
var collection = (typeof collectionOrClosure == 'function') ? collectionOrClosure() : collectionOrClosure;
var object = collection.findById(options.data.idref);
if (object == null)
console.log("Error: Could not find object with id " + options.data.idref + " in ", collection);
return object;
}
}
Chiamo questo codice come segue:
var mapping = {
people: createMapping(Searcher),
topics: createMapping(Topic, this),
activeTopic: createReferenceMapping(function(){return self.topics();})
};
this.dataChannel.loadModel(function(data) {
ko.mapping.fromJS(data, mapping, this);
}
Questo si prende cura di entrambi la creazione di nuove istanze (tramite il constructor
funzione) e guardando quelli esistenti tramite lookup
.
Altri suggerimenti
Dai un'occhiata a EntitySpaces.js, c'è un video che puoi guardare, supporta modelli di dati gerarchici completi e genererà persino il tuo servizio WCF JSON, supporta anche le API REST.
Un framework JavaScript ORM (Accesso ai dati) che utilizza Knockout