Handlebars.js: Erro: Objeto de modelo desconhecido: string ao usar um modelo pré-compilado com .template ()

Criado em 12 dez. 2014  ·  4Comentários  ·  Fonte: handlebars-lang/handlebars.js

Estou tentando registrar um parcial, que de acordo com a documentação deve ser feito assim:

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

handlebars.registerPartial('stuff', template)

No entanto, o método .template() produz este erro:

Error: Unknown template object: string

Posso ver que compiledPartial acima é de fato uma string que se parece com um objeto:

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

WTF?

Nó 0.10.25, Handlebars 2.0.0

Comentários muito úteis

Estou escrevendo um aplicativo do lado do servidor que precisa ser capaz de pré-compilar os modelos (e, em seguida, entregá-los ao cliente no caso de precisarem ser renderizados novamente com o novo contexto) e também renderizá-los em HTML (para cintilação menos perceptível / atraso no cliente + SEO aprimorado). Parece que preciso chamar precompile e compile separadamente ou preciso eval a saída serializada do pré-compilador. Nenhuma dessas abordagens parece muito elegante, então estou perdendo algo ou meu aplicativo é apenas incomum? (A propósito, este aplicativo foi escrito em Java, mas usando o mecanismo JavaScript integrado [Rhino / Nashorn] para a parte de modelagem; esperançosamente, isso não importa.)

Caso mais alguém tenha se confundido com a documentação da pré -

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)");
});

Todos 4 comentários

O método precompiler se destina a serializar o modelo e, em seguida, o método template é usado para restaurá-lo no cliente. Se você está tentando avaliar o modelo no mesmo processo, deve usar Handlebars.compile diretamente.

Obrigado pela resposta. Parece que os documentos são mais voltados para o uso de barras de guia no lado do cliente, já que é possível passar apenas a string parcial não compilada para o método registerPartial() , se você estiver usando barras de guia no lado do servidor.

Estou escrevendo um aplicativo do lado do servidor que precisa ser capaz de pré-compilar os modelos (e, em seguida, entregá-los ao cliente no caso de precisarem ser renderizados novamente com o novo contexto) e também renderizá-los em HTML (para cintilação menos perceptível / atraso no cliente + SEO aprimorado). Parece que preciso chamar precompile e compile separadamente ou preciso eval a saída serializada do pré-compilador. Nenhuma dessas abordagens parece muito elegante, então estou perdendo algo ou meu aplicativo é apenas incomum? (A propósito, este aplicativo foi escrito em Java, mas usando o mecanismo JavaScript integrado [Rhino / Nashorn] para a parte de modelagem; esperançosamente, isso não importa.)

Caso mais alguém tenha se confundido com a documentação da pré -

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, você deseja chamar compilar e pré-compilar. O código gerado para os dois é muito diferente e eu não presumiria que tentar toString ou similar funcionará com a saída de compilação, etc.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

ustun picture ustun  ·  6Comentários

janus-reith picture janus-reith  ·  3Comentários

ShintaroOkuda picture ShintaroOkuda  ·  7Comentários

morgondag picture morgondag  ·  5Comentários

rhariraman picture rhariraman  ·  5Comentários