2012-04-06 2 views
30

У меня есть приложение в Node.js с использованием Expressjs и Handlebars в качестве механизма шаблонов.Node.js с Handlebars.js на сервере и клиенте

Expressjs использует макеты, а затем отображает виды. Компоновка (layout.hbs) выглядит следующим образом:

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

{{{body}}} заменяется на стороне сервера, в node.js при доступе к маршруту. Например:

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

Заменит {{{body}}} тег с содержимым index.hbs.

Теперь, с клиентской стороны, я использую Backbone.js и хочу использовать Handlebars для представлений, управляемых через Backbone. Проблема в том, что, поскольку эти страницы уже обрабатываются с помощью Handlebars, когда я пытаюсь использовать Handlebars внутри него (или Handlebars in Handlebars), это не сработает. Ошибок нет, просто просто не заменяет теги данными.

Кто-нибудь сталкивался с этим раньше или имел какое-то представление о работе?

Спасибо!

ответ

13

Yup, это липкая проблема --- вроде как проблемы с цитированием в сценариях оболочки, которые становятся гнездом крыс в цитируемых цитатах.

Моим решением является использование jade (a la haml) в expressjs (на стороне сервера) для вывода шаблонов на основе дескрипторов для клиента. Таким образом, сервер использует один синтаксис (нефрит), а клиент использует другое (рули). Я на том же перекрестке, что и вы, поэтому у меня такая же проблема.

Конечно, нефрит не является существенным (хотя он готов для экспресс). Вы можете выбрать любой механизм шаблонов (не для рулей) для сервера и/или вы могли бы использовать рули на сервере с шаблонами шаблонов без рулей на клиенте --- пока два синтаксиса выбранных вами шаблонных двигателей не сталкиваются. Поскольку я использую emberjs на клиенте, и он использует синтаксис handlebars (по умолчанию), я предпочитаю использовать emberjs + handlebars синтаксис на клиенте. Таким образом, expressjs + jade стал естественным подходом для сервера.

+0

Справедливо, звучит, как будто мне придется использовать другой механизм шаблонов - спасибо! – dzm

+0

Добро пожаловать. Рад был помочь. – occam

+0

Хотя использование Jade, похоже, является решением, я не уверен. Если вы найдете другое решение, я буду очень рад ... на данный момент я считаю, что использование Jade и Angular.js - это мое облегчение! –

11

Бесстыдные саморекламы!

Я хотел сделать это же обмена клиент/сервер вещь, так что я написал небольшой пакет NPM, чтобы помочь:

node-handlebars-precompiler

Я взбитыми его в течение нескольких часов на основе команды -line компилятор в репозитории ручек wycats. Это не самый лучший код в мире, но он очень хорошо работает для меня.

EDIT: Я больше не поддерживаю этот пакет. Если вы хотите взять на себя ответственность, свяжитесь со мной через Github. В основном я использую шаблоны Jade, поэтому для меня не имеет смысла продолжать работу в качестве сопровождающего.

4

Я работал над этим, передавая клиентские шаблоны через серверные шаблоны.

Так на стороне сервера прочитать все на стороне клиента шаблоны для массива и передать его в визуализации функции на стороне сервера

В обработчике маршрута сделать что-то вроде:

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

А потом в layout.hbs:

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

Здесь я использую имена файлов без расширений как шаблона, так что на них можно ссылаться с видом на позвоночнике. О, и не забудьте реализовать кэширование для режима производства.

Да, это отстой.

Я думаю, что для этого нужно написать Handlebars/Express/Connect.

70

Вы должны использовать предварительно скомпилированные шаблоны клиентов. Они быстрее выполняются и позволяют использовать один и тот же язык шаблонов на сервере и клиенте.

  1. Установите рули глобально npm install handlebars -g
  2. Прекомпилировать шаблоны handlebars client-template1.handlebars -f templates.js
  3. Включить templates.js <script src="templates.js"></script>
  4. Выполнить шаблон var html = Handlebars.templates["client-template1"](context);

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

+5

Это гораздо лучшее решение, чем принятый ответ, imo – Paul

+3

еще проще теперь https://npmjs.org/package/grunt-contrib-handlebars – slf

27

Простой способ сделать это просто приложение end a \ до {{ в файле Handlebars. Например:

<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> 

Приведенный выше код будет оказано на клиенте с {{..}} тэги сохранились.

+0

Действительно? Черт, я бы хотел знать это год назад. Это хорошо и просто. –

+0

Работы любят удовольствие! –

+1

Это отлично поработало, я бы хотел, чтобы они поместили это в документацию ... или, может быть, я просто пропустил это. – skud

1

У вас есть 2 варианта. Второй лучший способ пойти:

1) Побег усов

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

2) PreCompile

будет скомпилирован шаблон на сервере, прежде чем он идет к клиенту. Это сделает шаблон готовым к использованию и уменьшит нагрузку на браузер.

0

Мне не понравилось решение для предварительной компиляции (потому что я хочу определить шаблоны в том же файле, где я буду использовать их), ни наивное решение для удаления \{{ (потому что ему нужен полный компилятор Handlebars и еще javascript-код), поэтому я придумал гибридное решение, которое использует хелперы рули:

1) Регистрация нового помощника под названием „шаблон“ на конфигурации сервера

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) Используйте его в любом месте на стороне клиента веб-страницу (с \{{ escape f или на стороне клиента параметры)

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

(сервер будет перекомпилировать его в чем-то вроде этого)

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


3) Просто вызовите функцию, где вам это нужно в стороне клиента Javascript

var generatedHtml = myTemplate("world"); // = <div><p>Hello world!</p></div> 
$("#myDiv").html(generatedHtml);   // or whatever 
Смежные вопросы