【问题标题】:How do I reduce view duplication between client and server?如何减少客户端和服务器之间的视图重复?
【发布时间】:2010-09-25 18:46:51
【问题描述】:

我正在做一个 AJAXy 项目(Dojo 和 Rails,如果细节很重要的话)。有几个地方用户应该能够对结果进行排序、分组和过滤。还有一些地方,用户填写一个简短的表格,然后将生成的项目添加到同一页面上的列表中。

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

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

那么问题一:有没有一个好的 Javascript MVC 框架我们可以用来使客户端的渲染更易于维护?

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

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

【问题讨论】:

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


    【解决方案1】:

    好吧,每次您在客户端和服务器上生成 HTML sn-ps 时,您都可能会得到重复的代码。一般没有什么好的办法。但是你可以做两件事:

    1. 在服务器上生成所有内容。当您需要动态生成 HTML sn-ps 时,请使用 AHAH。基本上,您要求服务器生成一个 HTML 片段,异步接收它,然后使用 innerHTML 或任何其他类似机制将其插入到位。
    2. 在客户端上生成所有内容(AKA 胖客户端范例)。在这种情况下,即使对于初始渲染,您也传递数据而不是预渲染 HTML,并使用 JavaScript 在客户端处理数据以生成 HTML。根据情况,您可以使用数据岛技术,或异步请求数据。变体:使用JSONP 将其包含为

    这两种方法都非常简单,并且各有利弊。有时可以在一个 Web 应用程序中将这两种技术结合起来用于不同部分的数据。

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

    【讨论】:

    • 1.除非您解析返回的 HTML,否则 AHAH 不允许您执行过滤、排序或分组等操作。解析可以非常简单,因为您可以创建任意 HTML 类,但这似乎还是有点浪费。 2.如果需要支持非JS,不解决重复问题。
    • 1.这取决于你在你的 sn-p 中生成了什么样的钩子。自定义属性 + dojo.query() 可以创造奇迹。 2.如果你的客户端没有JS——我们在说什么代码重复?在服务器上?
    【解决方案2】:

    我没有完整的答案给你;在最近的一个项目中,我也为此苦苦挣扎。但是,这里有一个想法:

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

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

    【讨论】:

    • 当然可以。但是,每次我选择按不同的列对表进行排序时,服务器上的开销都会很大。更不用说带宽限制了。
    【解决方案3】:

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

    服务器端:

    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 可以让您在不访问服务器的情况下进行排序、过滤、分组等操作。

    我只是谨慎,因为我从未听说过这样做。似乎有一个反模式潜伏在那里......

    【讨论】:

      【解决方案4】:

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

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

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

      随着您的客户规模不断扩大,您需要一个丰富而灵活的 MVC,请尝试使用 PureMVC。 http://puremvc.org/content/view/102/181/

      【讨论】:

      • 我在最近的一个项目中成功地做到了这一点。主要的权衡是 A) 非 JS 浏览器没有后备 B) 潜在的性能问题 (IE6/7) 渲染大型 HTML
      【解决方案5】:

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

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

      ExtJS 中创建此类控件相对容易 - 看看this article

      【讨论】:

        【解决方案6】:

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

        排序、过滤

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

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

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

        新项目

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

        为了将新项目添加到结果表中,我将克隆一行并更改值。同样,我们不需要在客户端渲染任何东西。上次我需要这样的东西时,我在结果的末尾添加了一个空的隐藏行,这样无论结果是否为空,您都将始终有一行要克隆。

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            猜你喜欢
            • 2011-11-05
            • 2016-01-29
            • 2023-03-12
            • 2011-02-10
            • 2016-09-26
            • 1970-01-01
            • 2011-05-16
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多