如何减少客户端和服务器之间的视图重复?

时间:2008-12-07 22:32:26

标签: javascript ruby-on-rails ajax model-view-controller

我正在开发一个AJAXy项目(Dojo和Rails,如果细节很重要的话)。用户应该可以在几个地方对结果进行排序,分组和过滤。还有一些地方用户填写了一个简短的表格,结果项目被添加到同一页面上的列表中。

非AJAXy实现工作正常 - 视图层服务器端已经知道如何渲染这些东西,因此它可以以不同的顺序或使用额外的元素再次执行。但是,这给服务器增加了很多负担。

所以我们切换到从服务器发送JSON并进行大量(重新)渲染客户端。缺点是现在我们有重复的代码用于呈现每个页面:一次是在Rails中,这是为此构建的,一次是在Dojo中,而不是。后者基本上只是字符串连接。

问题第一部分:我们可以使用一个很好的Javascript MVC框架来使客户端的呈现更易于维护吗?

问题第二部分:有没有办法在Javascript中生成客户端视图,在ERB中从同一模板生成服务器端视图?我认为这就是实用程序员会做的事情。

或者,问题第三部分:我是否完全错过了另一个角度?也许从服务器发送JSON,但也包含HTML片段作为属性,以便Javascript可以进行过滤,排序等,然后只插入给定的片段?

7 个答案:

答案 0 :(得分:1)

好吧,每次在客户端和服务器上生成HTML代码段时,最终都会出现重复的代码。一般来说没有好办法。但你可以做两件事:

  1. 在服务器上生成所有内容。需要动态生成HTML代码段时,请使用AHAH。基本上,您要求服务器生成HTML片段,异步接收,并使用innerHTML或任何其他类似机制将其插入到位。
  2. 在客户端上生成所有内容(AKA是胖客户端范例)。在这种情况下,即使是初始渲染,您也可以传递数据而不是预渲染的HTML,并使用JavaScript处理数据客户端以制作HTML。根据具体情况,您可以使用数据岛技术,或异步请求数据。变体:将其包含为< script>使用JSONP,以便浏览器在加载页面时向您发出请求。
  3. 这两种方法都很简单,各有利弊。有时,可以将一种Web应用程序中的两种技术组合用于不同的数据部分。

    当然,您可以使用异乎寻常的解决方案,例如使用一些基于JavaScript的服务器端框架。在这种情况下,您可以在服务器和客户端之间共享代码。

答案 1 :(得分:0)

我没有完整的答案给你;在最近的一个项目中,我也一直在努力解决这个问题。但是,这是一个想法:

  • Ajax调用Rails
  • Rails再次使用新行组成整个网格。
  • Rails序列化HTML,返回浏览器。
  • Javascript用新的HTML替换整个网格元素。

注意:我不是Rails的人,所以我不确定这些是否合适。

答案 2 :(得分:0)

有没有人尝试过类似下面的内容?现在有冗余数据,但所有渲染都在服务器端完成,所有交互都在客户端完成。

服务器端:

render_table_initially:
  if nojs:
    render big_html_table
  else:
    render empty_table_with_callback_to_load_table


load_table:
  render '{ rows: [
    { foo: "a", bar: "b", renderedHTML: "<tr><td>...</td></tr>" },
    { foo: "c", bar: "d", renderedHTML: "<tr><td>...</td></tr>" },
    ...
  ]}'

客户方:

dojo.xhrGet({
  url: '/load_table',
  handleAs: 'json',
  load: function(response) {
    dojo.global.all_available_data = response;
    dojo.each(response.rows, function(row) {
      insert_row(row.renderedHTML);
    }
  }
});

存储all_available_data可让您在不点击服务器的情况下进行排序,过滤,分组等。

我只是谨慎,因为我从来没有听说过这件事。似乎那里潜伏着一种反模式...

答案 3 :(得分:0)

“也许从服务器发送JSON,但也包含HTML片段作为属性,以便Javascript可以进行过滤,排序等,然后只插入给定的片段?”

我建议将表示层保留在客户端上,只需根据需要下载数据。

对于基本的模板引擎,您可以扩展Prototype的Template构造: http://www.prototypejs.org/api/template

随着您的客户扩展并且您需要丰富而灵活的MVC,请尝试使用PureMVC。 http://puremvc.org/content/view/102/181/

答案 4 :(得分:0)

与常规服务器端编程一样,您应该努力使用控件封装您的实体,在您的情况下,客户端控件具有数据属性并且还可以呈现方法+事件。

例如,假设您在页面上显示了一个显示员工树,实际上您应该将其行为封装在客户端类中,该类可以获取员工列表的JSON对象/默认情况下连接到服务和render方法来渲染输出,事件等。

ExtJS中创建这类控件相对容易 - 请查看this article

答案 5 :(得分:0)

也许我没有完全理解你的问题,但这就是我如何解决你的要求:

排序,过滤

它可以在JavaScript中完成,无需点击服务器。这是一个操纵表行,移动行进行排序,隐藏行进行过滤的问题,不需要重新渲染。您需要使用自定义属性或额外类名称标记具有数据类型的列,以便能够解析数字或日期。

如果您的报告是分页的,我认为刷新整个表格或页面会更容易也更好。

我在这里无法帮助,因为我不明白你将如何启用分组。您是否切换列以显示累积?如何显示不支持累积的数据,如文本或日期?

新项目

这次我将使用带有JSON响应的AJAX来确认新项目是否已正确保存,并可能包含计算数据。

为了将新项添加到结果表中,我将克隆一行并更改值。同样,我们不需要在客户端呈现任何内容。我最后一次需要这样的东西时,我在结果的末尾添加了一个空的隐藏行,这样,无论结果是否为空,你都会有一行克隆。

答案 6 :(得分:0)

我的list of five AJAX styles中的第5号往往效果很好。