2014-04-21 22 views
6

Voglio creare un oggetto javascript da un modello. Il problema è che non so come sarà il modello in anticipo. Come semplice esempio, se ho avuto la funzione di modelloCreare oggetti Javascript da un modello

template = function (data) { 
    return { 
     title: data.title 
    } 
} 

poi ho potuto correre template({ title: "Steve" }) e tornare l'oggetto

{ title: "Steve" } 

Perché data.title non viene analizzato fino a quando io chiamo la funzione template. Ma sto costruendo un oggetto basato sull'input dell'utente in cui i nomi dei campi non sono noti in anticipo e potrebbero essere nidificati profondamente ovunque nell'oggetto.

Se si definisce l'oggetto che viene restituito in precedenza, il campo data.title nell'esempio sarà già valutato e non utilizzerà i dati di input. Per esempio, io voglio essere in grado di definire l'oggetto modello come

obj = { title: this.title } 

quindi ridefinire il modello come

template = function() { 
    return obj 
} 

e chiamare template.call({title:"Steve"}). Ma al momento mi rimetto

{ title: undefined } 

perché this.title era già valutata quando ho definito obj. Forse mi sto avvicinando a questo modo sbagliato, perché continuo ad arrivare alla conclusione che dovrei modificare la funzione stringendola, modificando la stringa per includere il codice non valutato this.title e creando una nuova funzione dalla stringa. Ma sembra una pessima idea.

E attraversare l'oggetto alla ricerca di valori speciali da sostituire sembra costoso e complicato. Ho anche cercato una sorta di libreria di template di oggetti javascript ma non ho trovato nulla.

EDIT: Per rendere più chiaro che i dati di input e la struttura del modello non necessariamente corrispondere, mi può essere utile avere un modello che assomiglia

template = function (data) { 
    return { 
     name: "Alfred", 
     stats: { 
      age: 32, 
      position: { 
       level: 10, 
       title: data.title 
      } 
     } 
    } 
} 

e chiamare template({title:"Manager"}) per ottenere

{ "name": "Alfred", "stats": { "età": 32, "posizione": { "livello": 10, "title": "manager" } }}

+0

http://api.jquery.com/jquery.extend/ – setec

+0

Grazie, ma forse io avrei dovuto essere più chiaro: il problema di questo è che t I dati di input non corrisponderanno alla struttura del modello. I valori di input potrebbero dover essere collocati in una parte profondamente annidata dell'oggetto o più volte all'interno dello stesso oggetto. Non voglio "sapere" come appare quando chiamo la funzione template. –

risposta

5

Così sono riuscito a risolvere questo problema (ab) utilizzando funzioni come metadati per contrassegnare i valori che dovrebbero essere sostituiti nel modello. Ciò è reso possibile da due cose:

  1. Ho solo bisogno valori validi JSON, quindi può tranquillamente dire che funzioni non sono input dell'utente letterale
  2. JSON.stringify ha un replacer parameter che attraverserà l'oggetto e può essere utilizzato per passare i dati di ingresso al modello

Utilizzando un generatore di modello come questo

var templateMaker = function (object) { 
    return function (context) { 
     var replacer = function (key, val) { 
      if (typeof val === 'function') { 
       return context[val()] 
      } 
      return val; 
     } 
     return JSON.parse(JSON.stringify(obj, replacer)) 
    } 
} 

creo un oggetto modello, sostituendo f nomi ield con funzioni che restituiscono il nome del campo

var obj = { 
    name: "Alfred", 
    stats: { 
     age: 32, 
     position: { 
      title: function() { return 'title' }, 
      level: function() { return 'level' } 
     } 
    } 
} 

poi creare la funzione di modello, definiscono il mio ingresso, e lo rendono un oggetto

var template = templateMaker(obj); 

var data = { 
    title: "Manager", 
    level: 10 
} 

var rendered = template(data); 

e magicamente, l'uscita oggetto assomiglia

{ "name": "Alfred", "stats": { "age": 32, "position": { "title": "Manager", "level": 10 } } }

3

motori Forse template come Mustache avrebbero aiutarvi in ​​questo.

È possibile definire il modello oggetto nella stringa:

var template = '{ title: {{title}} }';

poi renderlo con i dati, e convertirlo in JSON:

var data = {title: 'I am title'}; 
var obj = JSON.parse(Mustache.render(template, data)); 

UPDATE:

Ho letto il tuo esempio aggiornato, ecco l'esempio corrispondente:

var template = JSON.stringify({ 
    name: "Alfred", 
    stats: { 
     age: 32, 
     position: { 
      level: 10, 
      title: '{{title}}' 
     } 
    } 
}); 

var data = {title: 'I am title'}; 
var obj = JSON.parse(Mustache.render(template, data)); 

obj.stats.position.title == "I am title"; 
+0

Grazie. Ho considerato qualcosa del genere ma dato che l'utente detterà gli altri valori nell'oggetto, non ero sicuro di come distinguere il mio modello '{{var}}' dall'input dell'utente dove volevano letteralmente la stringa "{{var} }". C'è forse un modo banale per fare questo mi manca? –

+0

Non ho ancora trovato il modo di risolverlo. – wong2

Problemi correlati