11

(来自 Tristan McNab 的 Dart 讨论邮件列表)

我正在尝试构建一个服务器端 MVC 框架并基于模板等生成视图,我想知道是否可以动态应用 Dart 的字符串插值。例如,这将是我的视图模板:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>${ViewData["Title"]}</title>
    <link href="/Content/css/site.css" rel="stylesheet" />
  </head>
  <body>
    <h1>${ViewData["Title"]}</h1>
    <div id="container">
      <p>Hello world!</p>
    </div>
  </body>
</html>

我想使用以下方法应用 ViewData 变量:

static String applyViewData(String html, Map ViewData) {
    // apply interpolation here
}

目前这有可能吗?我对 API 的搜索表明它不是。

4

2 回答 2

8

(比尔·黑塞发布)

通过将字符串文字包装在将上下文作为参数的函数中,您可以拥有一个可以传递的 Function : context -> String 而不是 String。如果您需要对这些对象使用一些字符串操作,如 concat,您可以在封装此类型的类上实现这些操作(“提升”它们)。这似乎是一种在一个地方提供字符串文字并在另一个地方提供您想要插值的数据的简单方法。

字符串插值总是动态发生的,每次使用文字时,数据很容易来自函数的参数而不是词法上下文。

例如:

Function MyTemplate() {
   return (Context context) {
     return "<table><tr><td class=${context.leftColumnClass}>Red Sox</td><td>${context.data}</td></tr></table>";
   }
}

...

var templateHere = MyTemplate();

...

var output = templateHere(context);

您也可以跳过一个间接级别并创建

String FillMyTemplate(Context context) => '''
    <html><head><title>$context.title</title></head>
''';

并在需要模板的地方使用 FillMyTemplate。

于 2012-08-09T15:32:30.300 回答
4

(由山姆·麦考尔发布)

有一个技巧涉及noSuchMethod()

class Template {
  var _context;

  noSuchMethod(method, args) {
    if (!method.startsWith("get:")) return super.noSuchMethod(method, args);
    return _context[method.substring(4)];
  }

  abstract String template();

  String evaluate(context) {
    _context = context;
    try {
      return template();
    } finally { _context = null; }
  }
}

然后创建一个子类:

class MyTemplate extends Template { template() => """
  <title>$title</title>
  <h1>$title</h1>
""";}

最后,使用它!

final renderedText = new MyTemplate().evaluate({"title": "Hello, world"})
于 2012-08-09T15:30:40.393 回答