Handlebars.js: エラー:不明なテンプレートオブジェクト:.template()でプリコンパイルされたテンプレートを使用する場合の文字列

作成日 2014年12月12日  ·  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}

WTF?

ノード0.10.25、ハンドルバー2.0.0

最も参考になるコメント

テンプレートをプリコンパイルし(新しいコンテキストで再レンダリングする必要がある場合に備えてクライアントに配信し)、HTMLにレンダリングする(ちらつきが目立たないようにする)必要があるサーバー側アプリケーションを作成しています。クライアントでの遅延+改善されたSEO)。 precompilecompile両方を別々に呼び出す必要があるか、シリアル化されたプリコンパイラ出力をevalする必要があるようです。 これらのアプローチはどちらもあまりエレガントではないので、何かが足りないのでしょうか、それともアプリケーションが異常なのでしょうか。 (ところで、このアプリケーションはJavaで書かれていますが、テンプレート部分に組み込みの[Rhino / Nashorn] JavaScriptエンジンを使用しています。うまくいけば、それは問題ではありません。)

他の誰かがプリコンパイル

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直接使用する必要があります。

答えてくれてありがとう。 サーバー側でハンドルバーのみを使用している場合は、コンパイルされていない部分文字列のみをregisterPartial()メソッドに渡すことができるため、ドキュメントはクライアント側でハンドルバーを使用することを目的としているようです。

テンプレートをプリコンパイルし(新しいコンテキストで再レンダリングする必要がある場合に備えてクライアントに配信し)、HTMLにレンダリングする(ちらつきが目立たないようにする)必要があるサーバー側アプリケーションを作成しています。クライアントでの遅延+改善されたSEO)。 precompilecompile両方を別々に呼び出す必要があるか、シリアル化されたプリコンパイラ出力をevalする必要があるようです。 これらのアプローチはどちらもあまりエレガントではないので、何かが足りないのでしょうか、それともアプリケーションが異常なのでしょうか。 (ところで、このアプリケーションはJavaで書かれていますが、テンプレート部分に組み込みの[Rhino / Nashorn] JavaScriptエンジンを使用しています。うまくいけば、それは問題ではありません。)

他の誰かがプリコンパイル

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は、コンパイルとプリコンパイルを呼び出す必要があります。 この2つで生成されるコードは大きく異なり、toStringなどを実行しようとするとコンパイル出力などで機能するとは思いません。

このページは役に立ちましたか?
0 / 5 - 0 評価