Handlebars.js: Ошибка: неизвестный объект шаблона: строка при использовании предварительно скомпилированного шаблона с .template ()

Созданный на 12 дек. 2014  ·  4Комментарии  ·  Источник: handlebars-lang/handlebars.js

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

var partialString = fs.readFileSync(filename), {encoding: 'utf8'})
var compiledPartial = handlebars.precompile(partialString)
var template = handlebars.template(compiledPartial)

handlebars.registerPartial('stuff', template)

Однако метод .template() вызывает эту ошибку:

Error: Unknown template object: string

Я вижу, что compiledPartial выше действительно является строкой, которая выглядит как объект:

{"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
return "<div>Stuff</div>\n";
},"useData":true}

Какого черта?

Узел 0.10.25, Руль 2.0.0

Самый полезный комментарий

Я пишу серверное приложение, которое должно иметь возможность как предварительно компилировать шаблоны (и затем доставлять их клиенту, если их нужно повторно отрисовать с новым контекстом), так и отображать их в HTML (для менее заметного мерцания / задержка на клиенте + улучшенное SEO). Кажется, мне нужно либо вызвать precompile и compile отдельности, либо мне нужно eval сериализованный вывод прекомпилятора. Ни один из этих подходов не кажется изящным, так что я чего-то упускаю или мое приложение просто необычное? (Кстати, это приложение написано на Java, но с использованием встроенного движка JavaScript [Rhino / Nashorn] для части создания шаблонов; надеюсь, это не имеет значения.)

На случай, если кто-то еще запутался в документации по прекомпиляции и остановился здесь, я написал пример, чтобы проиллюстрировать, что происходит. (На самом деле, я написал это, потому что пытался понять, что я делал не так.)

var templateSources = {
    hi: "Hi, {{name}}.",
    bye: "Goodbye, {{name}}."
};
var compiledTemplates = {};
var serializedTemplates = {};
var deserializedTemplates = {};

Object.keys(templateSources).forEach(function(name) {
    // Use compile method to generate actual executable template (function)
    compiledTemplates[name] = Handlebars.compile(templateSources[name]);
    // Use precompile method to generate serialized JS (string)
    serializedTemplates[name] = Handlebars.precompile(templateSources[name]);
    // If we really want, we can deserialize these 
    deserializedTemplates[name] = Handlebars.template(evalPrecompiledTemplate(serializedTemplates[name]));
});

// (Yes, I know eval is dangerous)
function evalPrecompiledTemplate(s) {
    return eval("(function(){return " + s + "}());");
}

// Quick demonstration that these template functions work the same
var context = {
    name: "John Smith"
};

// Output: 
// Rendering template named hi with context: Object {name: "John Smith"}
// Hi, John Smith.(compiled)
// Hi, John Smith.(precompiled/deserialized)
// Rendering template named bye with context: Object {name: "John Smith"}
// Goodbye, John Smith.(compiled)
// Goodbye, John Smith.(precompiled/deserialized)
Object.keys(templateSources).forEach(function(name) {
  console.log("Rendering template named " + name + " with context:", context);
  console.log(compiledTemplates[name](context) + "(compiled)");
  console.log(deserializedTemplates[name](context) + "(precompiled/deserialized)");
});

Все 4 Комментарий

Метод precompiler предназначен для сериализации шаблона, а затем метод template используется для его восстановления на клиенте. Если вы пытаетесь оценить шаблон в том же процессе, вам следует использовать Handlebars.compile напрямую.

Спасибо за ответ. Кажется, что документы больше ориентированы на использование Handlebars на стороне клиента, поскольку можно передать только некомпилированную частичную строку методу registerPartial() , если вы используете Handlebars только на стороне сервера.

Я пишу серверное приложение, которое должно иметь возможность как предварительно компилировать шаблоны (и затем доставлять их клиенту, если их нужно повторно отрисовать с новым контекстом), так и отображать их в HTML (для менее заметного мерцания / задержка на клиенте + улучшенное SEO). Кажется, мне нужно либо вызвать precompile и compile отдельности, либо мне нужно eval сериализованный вывод прекомпилятора. Ни один из этих подходов не кажется изящным, так что я чего-то упускаю или мое приложение просто необычное? (Кстати, это приложение написано на Java, но с использованием встроенного движка JavaScript [Rhino / Nashorn] для части создания шаблонов; надеюсь, это не имеет значения.)

На случай, если кто-то еще запутался в документации по прекомпиляции и остановился здесь, я написал пример, чтобы проиллюстрировать, что происходит. (На самом деле, я написал это, потому что пытался понять, что я делал не так.)

var templateSources = {
    hi: "Hi, {{name}}.",
    bye: "Goodbye, {{name}}."
};
var compiledTemplates = {};
var serializedTemplates = {};
var deserializedTemplates = {};

Object.keys(templateSources).forEach(function(name) {
    // Use compile method to generate actual executable template (function)
    compiledTemplates[name] = Handlebars.compile(templateSources[name]);
    // Use precompile method to generate serialized JS (string)
    serializedTemplates[name] = Handlebars.precompile(templateSources[name]);
    // If we really want, we can deserialize these 
    deserializedTemplates[name] = Handlebars.template(evalPrecompiledTemplate(serializedTemplates[name]));
});

// (Yes, I know eval is dangerous)
function evalPrecompiledTemplate(s) {
    return eval("(function(){return " + s + "}());");
}

// Quick demonstration that these template functions work the same
var context = {
    name: "John Smith"
};

// Output: 
// Rendering template named hi with context: Object {name: "John Smith"}
// Hi, John Smith.(compiled)
// Hi, John Smith.(precompiled/deserialized)
// Rendering template named bye with context: Object {name: "John Smith"}
// Goodbye, John Smith.(compiled)
// Goodbye, John Smith.(precompiled/deserialized)
Object.keys(templateSources).forEach(function(name) {
  console.log("Rendering template named " + name + " with context:", context);
  console.log(compiledTemplates[name](context) + "(compiled)");
  console.log(deserializedTemplates[name](context) + "(precompiled/deserialized)");
});

@jacobq вы хотите вызвать компиляцию и предварительную компиляцию. Сгенерированный код для этих двух очень отличается, и я бы не стал предполагать, что попытка toString или аналогичный будет работать с выводом компиляции и т. Д.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги