如何将原子部分嵌入模板数据对象中

时间:2018-05-24 23:05:24

标签: json gulp handlebars.js assemble handlebarshelper

我使用把手并用自耕农和吞咽装配。

我希望通过在数据对象的上下文中调用它来使一些全局化的部分能够嵌套或注入另一个部分。

一个简单的例子是拥有一个链接列表,我可以在整个网站的内容中引用这些链接。这背后的原因是需要一致性。例如,如果我在页面上的文本中有一个链接,我在整个网站中引用了15次,但后来意识到我需要添加商标或修改文本,我想更新一次,而不是15次

这是我想要做的一个例子。在json文件中定义全局数据:

links.json

<a href="{{href}}" {{#if target}}target="{{target}}"{{/target}}>{{linktext}}</a>

使用简单或复杂的模板从该内容生成部分内容:

links.hbs

{
  "text": "If you need a computer, go to {{> link link.apple}}."
}

并且可以通过参考它来将那部分嵌入到另一部分中。这不起作用,但我一直在阅读有关自定义助手的内容,但无法弄清楚我将如何拦截部分并将其绑定到其他部分。

text.json

<p>
{{text}}
</p>

text.hbs

<p>
If you need a computer, go to <a href="http://www.apple.com" target="_blank">apple</a>.
</p>

compiled.html

Form_onload

如果您有建议或示例可以帮助我了解如何实现这一目标,我非常感谢您的支持。提前谢谢。

2 个答案:

答案 0 :(得分:0)

有一些关于Handlebars helpers in their docs的信息,但没有那么多。

由于您尝试在上下文中的属性值中使用句柄语法(例如text),因此手柄将不会呈现该值,因为它已经呈现模板。您可以创建自己的帮助程序,可以像这样呈现值:

Handlebars.registerHelper('render', function(template, options) {
  // first compile the template
  const fn = Handlebars.compile(template);

  // render the compiled template passing the current context (this) to
  // ensure the same context is use
  const str = fn(this);

  // SafeString is used to allow HTML to be returned without escaping it
  return new Handlebars.SafeString(str);
});

然后你可以在你的模板中使用这样的帮助:

{{render text}}

答案 1 :(得分:0)

感谢@doowb的示例,您的代码确实有效但不是我想要做的。我真的想要更复杂的东西,但我简化了我的问题,不知道这将是一个问题。您提供的代码(我认为经过轻微调整后)可以简单地渲染模板,但我的模板使用帮助器,如#each和#if导致问题。帮助者在我的模板中,我最终获得了异步占位符。例如:<a $ASYNC$1$3...>我后来才知道这与部分的呈现方式有关。理解这导致我的子表达式和下面的解决方案。

通过一些修改保持我的上面的例子,这就是我能够合并部分的方式。

首先,我将text.json中的占位符简化为基本上唯一的ID,而不是尝试在那里渲染部分。

在我正在渲染的hbs模板上,例如页面或其他什么,我包含了带有3个参数的插入助手。前两个是子表达式,每个子表达式返回一个扁平的部分作为字符串。这里的关键是子表达式处理并在使用帮助程序完成当前进程之前返回结果。因此,将两个展平的模板与占位符一起发送给帮助程序以进行搜索。

帮助程序使用正则表达式模式中的第三个参数。它搜索第二个参数(展平的父模板)以获取此模式。找到后,它会用第一个参数替换模式的每个实例(是的,它是一个全局精细替换)。

因此,每次找到占位符时,展平的子字符串都会插入到父级中。

第一个论点

(partial "link" link.apple)

返回

'<a href="http://www.apple.com" target="_blank">apple</a>'

第二个论点

(partial "text" text.text-example)

返回

'<p class="text font--variant">If you need a computer, go to {{linkToApple}}.</p>'

第三个论点

'linkToApple'

<强> text.json

{
    "text-example": {
        "elm": "quote",
        "classes": [
            "text",
            "font--variant"
        ],
        "text": "If you need a computer, go to {{linkToApple}}."
    }
}

<强> text.hbs

 <{{elm}} class="{{#eachIndex classes}}{{#isnt index 0}} {{/isnt}}{{item}}{{/eachIndex}}">{{text}}</{{elm}}>

<强> compile.hbs

 {{insert (partial "link" link.apple) (partial "text" text) 'linkToApple' }}

<强> compile.html

 <p class="text font--variant">If you need a computer, go to <a href="http://www.apple.com" target="_blank">apple</a>.</p>

<强> gulpfile.js

app.helper('insert', function(child, parent, name) {
    const merged = parent.replace(new RegExp('\{\{(?:\\s+)?(' + name + ')(?:\\s+)?\}\}', 'g'), child);
    const html = new handlebars.SafeString(merged);
    return html;
});

希望这有助于其他人。我知道这可以使用改进,当我回到清理我的gulp文件时,我会尝试更新它。