18

我正在加载包含以下数据的模板:

"slides": [
    {
        "template": "video",
        "data": {
            "video": ""
        }
    },
    {
        "template": "image",
        "data": {
            "image": ""
        }
     }
]

在我的模板中,我想循环播放这些幻灯片并根据配置的模板加载部分

{{#each slides}}
    {{> resources_templates_overlay_video }}
{{/each}}

我怎样才能使这个部分加载动态(基于配置的模板)?

我正在使用require-handlebars-plugin

4

3 回答 3

15

据我所知,hbs 期望在编译时知道部分,这是在您传递数据之前。让我们解决这个问题。

首先,在渲染之前拉入你的动态部分,比如:

// I required the main template here for simplicity, but it can be anywhere
var templates = ['hbs!resources/templates/maintemplate'], l = data.slides.length;
for (var i=0; i<l; i++ )
    templates.push('hbs!resources/templates/overlay/'+data[i].template);

require(templates, function(template) {
    var html = template(data);
});

并定义一个将充当动态部分的助手

define(['Handlebars'], function (Handlebars) {

    function dynamictemplate(template, context, opts) {
        template = template.replace(/\//g, '_');
        var f = Handlebars.partials[template];
        if (!f) {
            return "Partial not loaded";
        }

        return new Handlebars.SafeString(f(context));
    }

    Handlebars.registerHelper('dynamictemplate', dynamictemplate);
    return dynamictemplate;
});

最后,修改你的主模板看起来像

{{#each slides}}
    {{dynamictemplate this.template this.data}}
{{/each}}
于 2012-11-16T17:53:53.690 回答
3

我发现上面的答案有点难以理解——它们泄漏了全局变量,有单字符变量,还有一些奇怪的命名。所以这是我自己的答案,供我(和你)参考:

使用“hbs”的动态部分,express.js 默认车把实现

我用它来制作一个简单的博客(article-name).md/blog/(article-name)创建一个动态部分:

// Create handlebars partials for each blog item
fs.readdirSync('blog').forEach(function(blogItem){
    var slug = blogItem.replace('.md','')
    var fileContents = fs.readFileSync('blog/'+blogItem, 'utf8')
    var html = marked(fileContents)
    var compiledTemplate = hbs.compile(html);
    hbs.registerPartial(slug, compiledTemplate);
})

// Create 'showBlogItem' helper that acts as a dynamic partial
hbs.registerHelper('showBlogItem', function(slug, context, opts) {
    var loadedPartial = hbs.handlebars.partials[slug];
    return new hbs.handlebars.SafeString(loadedPartial(context));
});

这是路线。如果部分不存在,则 404s,因为博客不存在。

router.get('/blog/:slug', function(req, res){
    var slug = req.param("slug")
    var loadedPartial = hbs.handlebars.partials[slug];
    if ( ! loadedPartial ) {
        return res.status(404).json({ error: 'Article not found' })
    }
    res.render('blog', {
        slug: slug
    });
})

/views/blog.hbs好像:

<div class="blog">
    {{ showBlogItem slug }}
</div>
于 2015-02-12T15:31:18.090 回答
2

Handlebars.partials[]返回一个原始字符串时,这意味着部分未编译。

我不确定,但我最好的猜测是 Handlebars 在编译包含部分的模板时会在内部编译部分。因此,当您使用帮助程序包含部分内容时,Handlebars 无法识别它并且不会被编译。

您可以自己编译部分。不要忘记注册已编译的部分,否则每次需要部分时都会编译,这会损害性能。像这样的东西应该工作。

var template = Handlebars.partials['templatename'],
    fnTemplate = null;

if (typeof template === 'function') {
  fnTemplate = template;
} else {
  // Compile the partial
  fnTemplate = Handlebars.compile(partial);
  // Register the compiled partial
  Handlebars.registerPartial('templatename', fnTemplate);  
}

return fnTemplate(context);
于 2014-09-11T22:04:36.073 回答