0

我正在使用车把并与 yeoman 和 gulp 组装。

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

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

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

链接.json

{
  "apple": {
    "linktext": "apple",
    "target": "_blank",
    "href": "http://www.apple.com"
  },
  "blog-article-foo-bar": {
    "linktext": "foo bar",
    "href": "http://www.foobar.com"
  },
  "dell": {
    "linktext": "dell",
    "target": "_parent",
    "href": "http://www.dell.com"
  }
}

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

链接.hbs

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

并且能够通过以某种方式引用它来将该部分嵌入到另一个部分中。这不起作用,但我一直在阅读有关自定义助手的内容,但不知道如何拦截部分并将其绑定到另一个部分。

文本.json

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

文本.hbs

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

编译的.html

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

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

4

2 回答 2

0

他们的文档中有一些关于Handlebars 助手的信息,但没有那么多。

由于您尝试在上下文(例如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}}
于 2018-05-26T12:52:44.580 回答
0

Thanks for the example @doowb, your code did work but not for what I was trying to do. I really wanted something more complicated but I simplified my question not knowing it would be an issue. The code you provided worked (I think after a slight tweak) for a simple render of a template, but my templates use helpers such as #each and #if which caused the issue. Where the helpers were in my template, I ended up getting async placeholders. For example: <a $ASYNC$1$3...> I later learned this has to do with how partials are rendered. Understanding that lead me to subexpressions and the below solution.

Keeping my example above with some modifications, this is how I was able to merge partials.

First, I simplified the placeholder in text.json to basically a unique ID, instead of trying to render the partial there.

On the hbs template that I'm rendering to, such as a page or whatever, I included the insert helper with 3 arguments. The first two are subexpressions, each return a flattened partials as strings. The key here is that subexpressions process and return a result before finishing the current process with the helper. So two flattened templates are then sent to the helper along with the placeholder to search for.

The helper uses the third argument in a regex pattern. It searches the second argument (flattened parent template) for this pattern. When found, it replaces each instance of the pattern with the first argument (yes its a global fine replace).

So, the flattened child string gets inserted into parent each time placeholder is found.

First argument

(partial "link" link.apple)

Returns

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

Second argument

(partial "text" text.text-example)

Returns

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

Third argument

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

Hope this helps someone else. I know this can use improvements, I'll try to update it when I get back to cleaning up my gulp file.

于 2018-06-14T00:37:05.787 回答