Handlebars.js: Fehler: Unbekanntes Vorlagenobjekt: Zeichenfolge bei Verwendung einer vorkompilierten Vorlage mit .template()

Erstellt am 12. Dez. 2014  ·  4Kommentare  ·  Quelle: handlebars-lang/handlebars.js

Ich versuche, einen Teil zu registrieren, was laut den Dokumenten so erfolgen sollte:

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

handlebars.registerPartial('stuff', template)

Die Methode .template() erzeugt jedoch diesen Fehler:

Error: Unknown template object: string

Ich kann sehen, dass das obige compiledPartial tatsächlich ein String ist, der wie ein Objekt aussieht:

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

WTF?

Knoten 0.10.25, Lenker 2.0.0

Hilfreichster Kommentar

Ich schreibe eine serverseitige Anwendung, die in der Lage sein muss, Vorlagen sowohl vorkompilieren (und sie dann an den Client zu liefern, falls sie mit neuem Kontext neu gerendert werden müssen) als auch in HTML rendern (für weniger auffälliges Flimmern/ Verzögerung beim Client + verbesserte SEO). Es scheint, dass ich entweder precompile und compile separat aufrufen muss oder ich muss eval die serialisierte Precompiler-Ausgabe aufrufen. Keiner dieser Ansätze fühlt sich sehr elegant an, also übersehe ich etwas oder ist meine Anwendung einfach ungewöhnlich? (Übrigens, diese Anwendung ist in Java geschrieben, verwendet aber die integrierte JavaScript-Engine [Rhino/Nashorn] für den Vorlagenteil; das spielt hoffentlich keine Rolle.)

Für den Fall, dass jemand anderes von der Dokumentation zur Vorkompilierung verwirrt wurde und hier

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

Alle 4 Kommentare

Die Methode precompiler dient zum Serialisieren der Vorlage und anschließend wird die Methode template verwendet, um sie auf dem Client wiederherzustellen. Wenn Sie versuchen, die Vorlage im gleichen Prozess auszuwerten, sollten Sie Handlebars.compile direkt verwenden.

Danke für die Antwort. Es scheint, dass die Dokumentation eher auf die Verwendung von Handlebars auf der Clientseite ausgerichtet ist, da es möglich ist, nur den nicht kompilierten Teilstring an die Methode registerPartial() , wenn Sie Handlebars nur auf der Serverseite verwenden.

Ich schreibe eine serverseitige Anwendung, die in der Lage sein muss, Vorlagen sowohl vorkompilieren (und sie dann an den Client zu liefern, falls sie mit neuem Kontext neu gerendert werden müssen) als auch in HTML rendern (für weniger auffälliges Flimmern/ Verzögerung beim Client + verbesserte SEO). Es scheint, dass ich entweder precompile und compile separat aufrufen muss oder ich muss eval die serialisierte Precompiler-Ausgabe aufrufen. Keiner dieser Ansätze fühlt sich sehr elegant an, also übersehe ich etwas oder ist meine Anwendung einfach ungewöhnlich? (Übrigens, diese Anwendung ist in Java geschrieben, verwendet aber die integrierte JavaScript-Engine [Rhino/Nashorn] für den Vorlagenteil; das spielt hoffentlich keine Rolle.)

Für den Fall, dass jemand anderes von der Dokumentation zur Vorkompilierung verwirrt wurde und hier

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 möchten Sie kompilieren und vorkompilieren. Der generierte Code für die beiden ist sehr unterschiedlich und ich würde nicht davon ausgehen, dass der Versuch, toString oder ähnliches zu verwenden, mit der Kompilierungsausgabe usw.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen