2

我一直在复制标记的地方遇到这种代码气味,我不确定如何修复它。这是一个典型的用例场景:

假设我们想对某种文章发表评论。在文章下方,我们看到了一堆评论。这些是与原始页面请求一起添加的,并由模板引擎生成(在我的例子中是 Freemarker,但它可以是 PHP 或其他)。

现在,每当用户添加评论时,我们都希望创建一个新的li元素并将其注入当前页面的评论列表中。假设这个li包含一堆东西,比如:

  1. 用户头像
  2. 他们的名字
  3. 一个链接可点击他们的个人资料或向他们发送私人消息
  4. 他们写的文字
  5. 他们写评论的日期
  6. 如果当前登录的用户有权执行这些操作,则一些“编辑”和“删除”链接/按钮。

现在,所有这些东西都已经写在我们最初生成页面的模板中了……所以现在我们必须在 Javascript 中复制它!

当然,我们可以使用另一种模板语言——比如 Jquery 的模板插件——来减轻生成和附加这个新的li块的痛苦......但我们仍然会得到重复的 html 标记,这些标记略有不同,因为我们不能使用宏或其他模板语言为我们提供的便利。

那么我们如何重构出重复项呢?有没有可能,还是我们只能忍受?解决此问题的最佳实践是什么?

4

1 回答 1

1

这是一个常见问题,并且随着 UI 复杂性的增加变得更加明显,并且必须对服务器和客户端模板进行更改。这个问题可以通过在客户端和服务器端使用相同的模板标记来解决。模板处理器必须用 JavaScript 和服务器端语言编写。

另外两个比上述方法更干净的解决方案,但都有自己的问题:

  • 做一切客户端
  • 做所有服务器端

如果所有标记生成都是在客户端完成的,那么服务器的行为或多或少就像一个 Web 服务,它只以适合应用程序的任何格式发送回数据。JSON 和 XML 是当今大多数 Web 服务非常流行的格式。客户端总是生成必要的 HTML 和 JS。如果采用这种方法,则必须明确定义客户端和服务器之间的边界。由于客户端对服务器上发生的事情的了解有限,这意味着必须定义正确的错误代码。状态管理将变得更加困难,因为大多数/所有服务器交互都将异步发生。使用这种方法添加评论的示例可能如下所示:

$('#add-comment').click(function() {
    var comment = $('#comment-box').text();
    $.ajax('http://example.com/add', {
        success: function() {
            addCommentRow(comment);
        },
        ...
    });
});

function addCommentRow(comment) {
    var user = currentUser().name;

    var html = "<li><b>{user}</b> says {comment}</li>";
    html = html.replace("{user}", user).replace("{comment}", comment);

    var item = $('<li>').html(html);
    $('#comments').append(item);
}

另一种方法是在服务器端做所有事情。每当发生更改时,向服务器发出请求,并要求它提供更新的视图。凭借快速的后端、不到一秒的响应时间以及适当的网络活动指标,尽管服务器上发生了所有事情,应用程序看起来应该非常响应。上面的例子将被简化为:

$('#add-comment').click(function() {
    $.ajax('http://example.com/add', {
        success: function(response) {
            $('#comments').html(response);
        },
        ...
    });
});

尽管这在客户端看起来比以前的方法更干净,但我们刚刚将标记生成移到了服务器上。但是,如果应用程序不像 Google 地图那样非常 AJAXy,那么这种方法可能更容易使用。同样,这是应用程序有多复杂的问题,也许维护状态客户端对您来说是必要的,在这种情况下,您可能希望使用以前的方法。

于 2010-12-12T09:54:21.573 回答