我正在尝试为即将推出的项目选择一个JS模板引擎,我最喜欢的一个似乎是dust.js。
我喜欢它是异步的想法,即我只是为渲染设置一些模板,当它准备就绪时,回调会将渲染的HTML插入到DOM中。
我不确定如何解决同步回调中的异步呈现问题。例如 - 我经常使用DataTables插件,它提供了一些回调,允许我在实际插入之前修改DOM节点。
为了说明问题 - 让我们假设我有一个以下片段(从DataTables website获取和修改):
$(document).ready( function() {
$('#example').dataTable( {
"fnRowCallback": function( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
// modify the node before it's actually inserted into the document
$('td:eq(4)', nRow).html( '<b>' + aData[4] + '</b>' );
}
} );
} );
现在 - 我想摆脱'<b>' + aData[4] + '</b>'
并使用一些上下文渲染的模板(这是一个简单的例子,但显示了问题)。
如果我理解正确,我不能强制dust.js
同步呈现模板,因此可能会发生未处理的节点将被插入到文档中(并且用户将看到它未经处理)以及稍后{ {1}}实际上呈现了将修改节点的模板。
从用户的角度来看,这显然不太好看。
情况确实如此(dust.js
不能强制同步)如果是的话 - 如何处理?我应该使用同步引擎,例如dust.js
还是handlebars
,或者我在这里看不到明显的东西?
非常欢迎任何帮助,见解或建议。 谢谢! :)
修改
这个问题不是关于如何渲染模板,而是关于如何确保在mustache
完成之前渲染它。感谢@robertklep将你的(已删除)答案指出来。
答案 0 :(得分:-2)
编辑:要明确,我认为这是一种不好的做法,你通常不应该做这样的事情。我将下面的代码仅仅作为一个例子,说明如果技术或架构限制强加于你,COULD如何做这样的事情。但是,它应该永远用作最后的手段。
我过去做过一些讨厌的事情,包括使用布尔值和循环来“捕获”异步调用,但我不会真的推荐它作为一个特别好的做法。不过,如果你想要它,就在这里。
// name is the template identifier, template is the template contents,
// data is the "context" of the template (its model), callback (optional)
// is the method you want the rendered template passed to, cbContext
// (optional) is the context in which you want the callback to execute
asyncToSync = function (name, template, data, callback, cbContext) {
// Tracks if it's time to return or not
var finished = false;
// Gives us an exit condition in case of a problem
var maxLoops = 10000;
// Create a variable to store the return value
var outVal = 'Template rendering did not finish';
// And the callback function to pass to dust
var dustCb = function (err, html) {
finished = true;
outVal = html;
}
var i = 0;
// We create this as a function so that increment goes to the bottom
// of the execution queue, giving dustCb a chance to execute before
// the counter hits max.
var incrementCounter = function () {
i += 1;
};
// Compile, load, and render the template
var compiled = dust.compile(template, name);
dust.loadSource(compiled);
// Pass our callBack so the flag gets tripped and outVal gets set
dust.render(name, data, dustCb);
// count up to maxLoops
while(!finished && (i < maxLoops)) {
incrementCounter();
}
// If a callback is defined, use it
if (callback) {
// If a callback context is defined, use it
return (cbContext) ? callback.call(cbContext, outVal) : callback(outVal);
}
// otherwise just return the rendered HTML
return outVal;
}