2012-04-06 22 views
30

Ho un'app in Node.js che utilizza Expressjs e Handlebars come motore di template.Node.js con Handlebars.js su server e client

Expressjs utilizza i layout e quindi visualizza le viste. Il layout (layout.hbs) si presenta così:

<!doctype html> 
<html lang="en"> 
    <head> 
    </head> 
    <body> 
    {{{body}}} 
    </body> 
</html> 

Il {{{body}}} è sostituito sul lato server, all'interno node.js quando si accede a un percorso. Per esempio:

app.get('/', function(req, res){ 
    res.render('index'}) 
}) 

sostituirà il tag {{{body}}} con il contenuto di index.hbs.

Ora, sul lato client sto usando Backbone.js e voglio usare Handlebars per le viste controllate tramite Backbone. Il problema è che poiché queste pagine sono già visualizzate tramite Handlebar, quando tento di utilizzare Handlebars al suo interno (o Handlebars all'interno di Handlebars) non funziona. Non ci sono errori, semplicemente non sostituisce i tag con i dati.

Qualcuno l'ha già incontrato prima o ha qualche idea di lavoro?

Grazie!

risposta

13

Sì, è un problema appiccicoso --- un po 'come i problemi di quoting in script di shell che diventano un ratto di citazioni citate.

La mia soluzione è utilizzare jade (a la haml) in expressjs (lato server) per generare modelli basati su manubri per il client. In questo modo, il server utilizza una sintassi (jade) e il client ne usa un altro (manubri). Sono allo stesso bivio di te, quindi ho la stessa sfida.

Ovviamente, la giada non è essenziale (anche se è già pronta per expressjs). È possibile scegliere qualsiasi motore di template (non-handlebars) per il server, e/o si può usare il manubrio sul server con i propri manubri non-template sul client --- a condizione che le due sintassi dei motori di template scelti non si scontrano. Dal momento che sto usando emberjs sul client e utilizza la sintassi del manubrio (di default), preferisco usare la sintassi di emberjs + manubri sul client. Quindi expressjs + jade è diventato un adattamento naturale per il server.

+0

Abbastanza corretto, sembra che dovrò utilizzare un motore di template diverso - grazie! – dzm

+0

Prego. Felice di aiutare. – occam

+0

Anche se usare Jade sembra essere la soluzione, non ne sono convinto. Se trovi altre soluzioni, sarò contento ... per ora credo che usare Jade e Angular.js sia il mio sollievo! –

11

Autopromozione senza vergogna!

ho voluto fare la stessa cosa client/server di condivisione, così ho scritto un piccolo pacchetto NPM per assistere:

node-handlebars-precompiler

ho sbattuto in su in un paio d'ore in base al comando -line compilatore nel repo dei manubri dei wycat. Non è il miglior codice al mondo, ma sta facendo il lavoro molto bene per me.

EDIT: Non sto più mantenendo questo pacchetto. Se vuoi prendere in consegna, per favore contattami tramite Github. Uso principalmente i modelli di giada ora, quindi non ha senso per me continuare come manutentore.

4

Ho lavorato a questo problema passando i modelli lato client attraverso i modelli lato server.

Così sul lato server leggere tutti i modelli client-side ad un array e passarlo alla funzione di rendering sul lato server

Nel vostro gestore di percorso fare qualcosa di simile:

readTemplates(function(err, clientTemplates) { 
    res.render("page", { 
    clientTemplates: clientTemplates; 
    }); 
}); 

e poi in layout.hbs:

{{#each clientTemplates}} 
<script type="text/handlebars id="{{this.filename}}" > 
{{{this.template}}} 
</script> 
{{/each}} 

Qui sto utilizzando nomi di file senza estensioni come il modello ID in modo che possano essere referenziati da vista backbone. Oh, e ricorda di implementare il caching per la modalità di produzione.

Sì, questo fa schifo.

Penso che dovremmo scrivere un helper Handlebars/Express/Connect per questo.

70

È necessario utilizzare modelli client precompilati. Sono più veloci nell'esecuzione e consentono di utilizzare lo stesso linguaggio di template sul server e sul client.

  1. Installare il manubrio a livello globale npm install handlebars -g
  2. Precompile i modelli handlebars client-template1.handlebars -f templates.js
  3. includono templates.js <script src="templates.js"></script>
  4. Eseguire il modello var html = Handlebars.templates["client-template1"](context);

https://stackoverflow.com/a/13884587/8360

+5

Questa è una soluzione molto migliore della risposta accettata, imo – Paul

+3

ancora più semplice ora https://npmjs.org/package/grunt-contrib-handlebars – slf

27

Un modo semplice per farlo è solo per app terminare a \ prima dello {{ in un file Handlebars. Per esempio:

<script type="text/x-template" id="todo-item-template"> 
<div class="todo-view"> 
    <input type="checkbox" class="todo-checkbox" \{{checked}}> 
    <span class="todo-content" tabindex="0">\{{text}}</span> 
</div> 

<div class="todo-edit"> 
    <input type="text" class="todo-input" value="\{{text}}"> 
</div> 

<a href="#" class="todo-remove" title="Remove this task"> 
    <span class="todo-remove-icon"></span> 
</a> 

Il codice di cui sopra saranno resi sul client con {{..}} tag conservati.

+0

Davvero? Dannazione, vorrei averlo saputo un anno fa. È carino e semplice. –

+0

Funziona come un piacere grazie! –

+1

Ha funzionato alla grande, vorrei averlo messo nella documentazione ... o forse l'ho perso. – skud

1

Hai 2 opzioni. Il secondo è il modo migliore per andare:

1) Scappa dai baffi

<script type="text/x-handlebars" data-hbs="example"> 
    <p>\{{name}}</p> 
</script> 

2) precompilare

Questo compilerà il modello sul server prima che va al cliente. Questo renderà il modello pronto per l'uso e ridurrà l'onere per il browser.

0

non mi piace la soluzione di precompilazione (perché voglio definire modelli nello stesso file in cui io li uso), né la soluzione ingenua \{{ fuga (perché ha bisogno il compilatore completo Manubrio e più codice javascript) così ho si avvicinò con una soluzione ibrida che utilizza aiutanti Manubri:

1) Registra un nuovo aiutante chiamato 'modello' a configurazione del server

var hbs = require('hbs'); 
hbs.registerHelper("template", function(key, options){ 
    var source = options.fn().replace("\\{{", "{{"); 
    var ret = 
    '<script>\n' + 
     key + ' = function(opt){\n' + 
      'return Handlebars.template(' + hbs.handlebars.precompile(source) + ')(opt);\n' + 
     '}\n' + 
    '</script>'; 
    return ret; 
}); 


2) Utilizzare ovunque nella vostra pagina web lato client (con \{{ escape f o di parametri sul lato client)

{{#template "myTemplate"}} 
    <div> 
     <p>Hello \{{this.name}}!</p> 
    </div> 
{{/template}} 

(il server precompilare in qualcosa di simile)

<script> 
    myTemplate = function(opt){ 
     return Handlebars.template(/* HBS PRECOMPILATED FUNCTION */)(opt); 
    } 
</script> 


3) È sufficiente chiamare la funzione in cui avete bisogno in JavaScript lato client

var generatedHtml = myTemplate("world"); // = <div><p>Hello world!</p></div> 
$("#myDiv").html(generatedHtml);   // or whatever 
Problemi correlati