2

使用Mason2构建网站。每个页面应该调用 3 个过滤器(方法,按内容调用):

<% $.filter1(args...) {{ %>
<% $.filter2(args...) {{ %>
<% $.filter3(args...) {{ %>

我对这些过滤器(方法)有 3 种不同的实现。这 3 个过滤器的默认设置是在顶级/Base.mc组件中定义的。

现在,对于网站的不同部分 - (不同的路线),比如说

/a/all/paths>/...>
/b/.....

需要使用上面的默认过滤器/方法集,但对于其他路由,

/c/...
/d/...
/e/...

需要使用另一组filter1, filter2,filter3

/x/....
/y/...

想用第三套。

这些方法可以很容易地在较低级别的组件中重新定义,但是按照(this question)中的方式进行操作并不符合 DRY 原则,例如在每个

/c/Base.mc
/d/Base.mc
/e/Base.mc

需要重复相同的 3

<%override filter1>
...
<%override filter2>
...
<%override filter3>

问题是:

  • 如何只编写一次方法的 3 种不同实现,以及如何一次使用它们?

我尝试制作一个组件,例如:/set2.mi,,/set3.mi我尝试覆盖那些过滤器方法,并在需要时调用/{c,d,e}/Base.mc

<& /set2.mi &>

但这不起作用。

如何编写 3 种不同的方法实现并在所需的 deeprr 中一次调用它们Base.mc?可能吗?

在标准 perl 我可能会使用角色,所以在需要的包中我会使用类似的东西:

with 'Set1';
with 'Set2';

Set1Set2将包含所需方法的实现,或用于动态加载的地方将使用require .... 在 Mason2 中是否有可能,或者我必须重复%ovverride

希望这是有道理的......如果没有,请添加评论,我会尝试更新问题。

编辑

例如,为了缩短代码,只使用一个过滤器而不是 3。

/Base.mc

<%augment wrap><% inner() %></%augment>

% #this is the "default" MyHead filter
<%filter MyHead($arg)>
    <!-- in the real code it is more complicated, but for an illustration it is enough -->
    <h1 class="<% $arg %>"><% $yield->() %></h1>
</%filter>

当在/a/index.mc使用它作为

% $.MyHead('big') {{
some head text
% }}

将输出如下:

<h1 class="big">some head text</h1>

现在,再来一个MyHead

<%filter MyHead($arg)>
    <!-- in the real code it is more complicated - basically want output different thing -->
    <h2 id="<% $arg %>"><% $yield->() %></h2>
</%filter>

如果我将上面的代码添加到我的/b/Base.mc它将工作,并MyHead/b/index.mc

% $.MyHead('modal') {{
some other text
% }}

将调用重新定义的过滤器,并将输出我想要的

<h2 id="modal">some other text</h2>

问题是,

  • 我不想在其他N个Base.mc组件中重复上面的过滤代码,比如in/c/Base.mc/d/Base.mc
  • 如何实现,编写一次过滤器并在许多其他组件中“使用”它以“重新定义”默认值。
4

1 回答 1

0

一种解决方案可能是(不是一个好的解决方案,并且会产生类似“意大利面条”的代码)使用继承链,如下所示:

  1. 从 中删除您的“默认”过滤器/Base.mc,因此它只包含<%augment wrap
  2. 创建一个名为例如的组件:BaseSetDefault.mc并进入其中,您的“默认”过滤器并将继承链显式设置为顶层/Base.mc
<%augment wrap><% inner() %></%augment>

<%filter MyHead($arg)><h1 class="<% $arg %>"><% $yield->() %></h1></%filter>

<%flags>
    extends => '/Base.mc'
</%flags>
  1. 同样,创建另一个名为 as 的组件/BaseSet2.mc并将您的“Set2”过滤器放在这里,例如:
<%augment wrap><% inner() %></%augment>

<%filter MyHead($arg)><h2 id="<% $arg %>"><% $yield->() %></h2></%filter>

<%flags>
    extends => '/Base.mc'
</%flags>
  1. 现在,在/a/Base.mc/b/Base.mc- 到处,你想要“默认”设置,改变链
<%flags>
    extends => '/BaseSetDefault.mc'
</%flags>
  1. /c/Base.mcand /d/Base.mc- 任何你想要“Set2”过滤器的地方,使用
<%flags>
    extends => '/BaseSet2.mc'
</%flags>

从现在开始,继承链/c/index.mc将是:

/c/index.mc -> /c/Base.mc -> /BaseSet2.mc -> /Base.mc

并且执行将作为

/Base.mc -augment-> /BaseSet2.mc -augment-> /c/Base.mc -main-> /c/index.mc
                    ^^^^^^^^^^^^ - defines the Set2 filters

对于/a/index.mc继承链

/a/index.mc -> /a/Base.mc -> /BaseSetDefault.mc -> /Base.mc

执行

/Base.mc -augment-> /BaseSetDefault.mc -augment-> /a/Base.mc -main-> /a/index.mc
                    ^^^^^^^^^^^^^^^^^^ - defines the "Default" filters

这不是很好的解决方案,但可以工作......

于 2014-09-21T12:11:56.560 回答