如何在 dust.js 中将默认值作为部分参数处理?

How to handle default value as partial parameters in dust.js?

我实际上做了一个简单的灰尘部分,我想给它一些默认值的参数。不是很容易解释,但这里有一个简单的例子:


部分

partials/hello.灰尘

{?label}{label}{:else}Hello{/label}: 
<span>{?name}{name}{:else}World{/name}</span>

partials/hello2.dust

{>"partials/hello"/} and 
{>"partials/hello" label="{label2}" name="{name2}"/}</div>

它应该如何工作的示例

test_0.dust

{>"partials/hello2" label="Peter" name="Parker" label2="Clark" name2="Kent"/}

Returns: "Peter:Parker and Clark:Kent"

test_1.dust

{>"partials/hello2" label2="Clark" name2="Kent"/}

Returns: "Hello:World and Clark:Kent"

test_2.dust

{>"partials/hello2" label="Peter" name="Parker"/}

Returns: "Peter:Parker and Hello:World"

test_3.dust

{>"partials/hello2"/}

Returns: "Hello:World and Hello:World"


在partials/hello.dust中,如果label & name变量没有定义,则用默认值替换(分别为"Hello"和"World")

所以在这里,test_0.dust 和 test_1.dust 将起作用,因为我提供了 label2 和 name2 参数。

在 partials/hello2.dust 中,我不知道这是否可以以一种优雅的方式进行,但我希望 label2 和 name2 变量具有不同的默认值,因此这不是强制性的提供它们(例如 "Hello2" 和 "World2")。

我能想到的一个解决方案是处理 hello2.dust 中所有可能的组合,包括相应的部分(即 label2 为空且 name2 为空,label2 为空且 name2 不为空,label2 不为空且 name2 为空, label2 不为空且 name2 不为空)但如您所见,它可能非常痛苦和丑陋。

明确地说,我希望能够做这样的事情:

partials/hello2.dust

{>"partials/hello"/}
{>"partials/hello" label="{?label2}{label2}{:else}Hello2{/label2}" name="{?name2}{name2}{:else}World2{/name2}"/}


解决方案

为了帮助别人,我终于做了自己的除尘助手:

'use strict';

module.exports = function (dust) {
    dust.helpers.default = function (chunk, ctx, bodies, params) {
        var resData, paramVals = {}, saveData = chunk.data;

        var localCtx = ctx;
        if (params) {
            localCtx = ctx.push(params);
        }
        for (var key in bodies) {
            if (key !== 'block') {
                chunk.data = [];
                resData = bodies[key](chunk, localCtx).data.join('');
                if (typeof ctx.get(key) === 'undefined') {
                    paramVals[key] = resData;
                }
            }
        }
        chunk.data = saveData;
        return bodies.block(chunk, localCtx.push(paramVals));
    };
};

所以,可以这样使用:

{@default}
{>"partials/mypartialusingname1"/}
hello {name1} & {name2} 
{:name1}Chuck Norris
{:name2}Walter White
{/default}

然后,如果 name1 和 name2 在当前上下文中不存在,则将其替换为一些默认值。

Dust 不包括为上下文设置默认值的工具。

这将是 Dust 助手的工作。这个助手的原始版本可能如下所示:

模板

{@defaultParam key="hello" value="moo"/}
{@defaultParam key="world" value="world"/}
{hello} {world}

上下文

{
    "hello": "hello"
}

帮手

dust.helpers.defaultParam = function(chunk, context, bodies, params) {
  var key = params.key,
      value = params.value;

  if(typeof context.get(key) === 'undefined') {
    context.global[key] = value;
  }
};

我们通过创建一个类似的助手解决了这个问题。在单个 @defaults 帮助程序声明中使用键值属性。

父模板

<!-- Standard partial include -->
{>"components/module-promo" /}

<!-- Partial include with overrides -->
{>"components/module-promo" title="Custom title override" caption="Custom caption" /}

部分

{@defaults
    title="Module title"
    caption="Module caption ipsum dolor sit amet."
/}

<article>
    <h2>{title}</h2>
    <p>{caption}</p>
</article>

帮手

dust.helpers.defaults = function(chunk, context, bodies, params) {
    for (var key in params) {
        context.global[key] = params[key];
    }
    return chunk;
};

(记住要 return 辅助函数中的 chunk。)

这对于同步模板渲染非常有效。我们将值存储在 context.global 上,并在部分编译时将它们存储在 add/modify 上。这意味着 global 发生了变化,但我们确实避免了使用相同参数名称的多个部分的问题。

如果尝试 stream/async 模板呈现,该方法会 运行 陷入麻烦。也许有人可以详细说明存储部分特定上下文值以改进这一点的最佳方法?