我应该在服务器端呈现 ajax 响应吗?

Posted

技术标签:

【中文标题】我应该在服务器端呈现 ajax 响应吗?【英文标题】:Should I render ajax responses on server side? 【发布时间】:2015-02-16 03:43:53 【问题描述】:

Django 和 Ajax 的新手。

我想知道一个关于良好实践网页设计的一般问题: 是否应该返回一个调用使用 ajax 的调用的视图函数,返回数据结构并将 html 页面的呈现留给客户端(意思是 javascript),还是呈现整个 HTML 并将其返回给 javascript 也是一种“好的”做法,所以它可以把它粘贴到代码中的某个地方吗?

我不希望我的模板的逻辑被 javascript 重复。我想使用模板来呈现 HTML 并将其返回给客户端。但是...这忽略了 ajax 的意义,不是吗?

我确实看到了这篇精彩的帖子: Rendering JSON objects using a Django template after an Ajax call

由于它很旧,我没有在那里发表回复,而是在这里恢复了这件事。 技术上可以在服务器端渲染吗?是的。 最佳实践?我不知道。

也许更好的做法是让我的 HTML 页面类型的“空白”已经形成良好的格式,并且只是来回传递数据。

我很想听听您对此事的意见。

在被搁置后,因为这个讨论往往是基于意见的(确实如此)并且这种格式不适合这个论坛,但我认为更新我的帖子以包含更精细的讨论分辨率会很好很多技术含义。

在您的“djangonian”体验中,构建网页(例如新闻提要)的最佳实践是可以通过 ajax 调用动态更新,从而返回客户端原始数据(例如使用 JSON ) 而不是预渲染的 HTML?

我会更具体: 我的网站有一个提要。 在该提要上,用户会看到许多帖子和每个帖子的 cmets。 每个帖子都是它自己的 HTML 表单,并且已经构建为 HTML。页面源示例:

<form id="post_looloo_by_testuser" method="post" action="/bz/login/" class="single_post_form">      
    <input type='hidden' name='csrfmiddlewaretoken' value='GfOHEMxx433XBUpg3yakTYPRQCVq132f' />
    <p class="box_single_post">
      <span name="post">
        <label class="single_post_form">
           says: looloo
        </label>
      </span>

      <span name="comments_for_post">
        <span name="single_comment">
          <label class="single_comment">
            testuser2 commented: moomoomoo
          </label>
        </span>
      </span>


      <span name="comments_for_post">
        <span name="single_comment">
          <label class="single_comment">
            testuser2 commented: qweqwe
          </label>
        </span>
      </span>


      <span name="add_comment">
        <input id="id_add_comment" maxlength="140" name="new_comment" type="text" placeholder="Add a comment..."/>
      </span>
    </p>
</form>

在顶部,就像在 facebook 上一样,用户可以立即添加新帖子。

<form id="add_post_form" method="post" action="" class="new_post_form" username="testuser">
  <input type='hidden' name='csrfmiddlewaretoken' value='GfOHEMxx433XBUpg3yakTYPRQCVq132f' />
  <span name="add_post">        
    <input id="id_add_post" maxlength="140" name="new_post" type="text" placeholder="Say something"/>
    <input id="add-post-btn" type="submit" name="submit" value="Add" username="testuser"/>
  </span>
</form>

“添加”按钮(实际上是表单的提交)随后会在服务器端调用我的应用程序中的某个视图的 ajax 调用。 我希望视图返回诸如拥有帖子的用户、帖子文本、cmets 列表等信息。 信息将以 JSON 或 XML 形式返回。不像预渲染的 HTML。 我想让我的 javascript 处理信息并使用顶部的新帖子更新用户的提要,同时避免刷新页面(因此使用 ajax)。

问题是用户当然可以添加无限数量的帖子(或有限数量,但大于一个)。为什么这有关系?看下面的问题:

我应该如何创建提要页面,以便我只使用动态检索的信息更新页面上的变量,并仍然允许添加更多帖子?

如果我事先知道只有一个这样的新帖子可用,那么我会创建一个预制的帖子表单,不可见,然后 javascript 会为该表单设置值并将其设置为可见。 但是用户添加的第二个帖子呢?第三个?等等……

我很想从您的经验中学习。 谢谢。

【问题讨论】:

您好,请注意。我编辑了我的帖子以更好地适应这个论坛的性质。谢谢。 【参考方案1】:

我认为退后一步并在这里打破一些术语很重要。渲染,当你使用它时,可能指的是几件事:

根据从一个或多个服务器接收到的数据,在浏览器中呈现 html 标记和 css 规则,以便为用户创建网页视图。 将数据呈现给服务器端的某种响应,供客户端浏览器或任何其他碰巧遵循正在使用的协议(本例中为 HTTP)的工具使用。

这些是完全不相关的不同活动,但我认为使用同一个术语来表示两者的能力可能会让您感到困惑。 Django 将对请求资源的 HTTP 查询呈现响应,该响应是否包含 HTML 或 JSON 或纯文本并不重要。

现在,也就是说,您是否想在创建网页方面做更多的工作以在服务器端(模板)或客户端(js)上以某种方式看起来更像是一个样式问题(有一些当然,考虑到您的特定用例可能产生的实用性)。

出于我自己的目的,我通常更喜欢在模板中呈现一般数据(可能是组织名称、有关导航的变量等),如果我要显示从数据库中提取的未知或大量数据,我' 将为此触发 AJAX 调用并向用户显示数据正在加载的指示。

但经验将指导您什么时候合适。

【讨论】:

【参考方案2】:

不,你不应该。

AJAX 调用应该只包含标准格式的请求资源,而不是一些自定义 HTML,例如,如果我请求 /cars,我希望得到一个标准格式的 car 实例列表(JSON或 XML),后端服务器不应该知道也不关心我如何呈现这些数据。

另外,在客户端生成 HTML 以避免通过网络传输不必要的数据也是一个好主意,假设我请求了一些 /cars 并获得了几十万个,每个都带有一个 HTML 表格标记。 .. 这是很多不必要的标记,可以添加到客户端而无需通过网络传输,因此它可以节省带宽,这一点很重要,尤其是对于移动用户。

最后,通过 AJAX 调用的端点的控制器应该很简单,并且不包含任何与视图相关的代码,首先要减少几毫秒的响应时间,其次,如果你想改变 UI,你会改变它在您的 HTML/CSS/JS 文件中,根据您的解决方案的复杂性,它可能完全是不同应用程序的一部分(如果您的应用程序仅用于为第三方 webapp 提供 API 怎么办?您会想要第三方应用程序来控制演示,而您只提供原始数据)。

关于您的编辑,我真的不明白向页面添加可能无限量的 HTML 元素有什么问题...您不需要在 HTML 文件中预先声明每个元素,您可以通过 Javascript 即时创建无限数量的它们,然后将它们插入到任何你想要的地方。

对于您的“我将如何处理 AJAX 驱动的新闻提要”问题,这取决于我的动机,它可以在带有可选 AJAX 刷新的基本服务器生成页面之间切换(模板同时存在于服务器和 Javascript 中将 AJAX 数据呈现给一个完整的 Ember 应用程序,服务器只提供一个 JSON API。

【讨论】:

我倾向于在设计方面同意这一点——用数据结构而不是形成的 HTML 来设计服务器端的响应更优雅且耦合更少。正如您所建议的,它还允许连接多种消费者类型。即网络浏览器、移动应用程序等。显然,我为在网络浏览器中显示而呈现的 HTML 可能对我的 HTC 来说不够好。如果我选择避免使用 HTML,我的原生 android 和/或原生 ios 应用程序当然会期望“原始”数据。但是 - 假设是这样。但仍然 - 我可以避免在 javascript 中重复我的模板吗? @dotaneli 您可以尝试搜索与框架无关的模板引擎,以便您可以在前端和后端重用相同的模板文件。另一种选择是在页面加载时直接在客户端呈现“动态”数据(您将通过 AJAX 刷新的数据),在这种情况下,模板的这些部分将仅使用 Javascript。 @dotaneli 哦,顺便说一句,没有浏览器需要“原始”数据,浏览器只是按照你的代码告诉它做什么,它不在乎关于设计模式或效率;我关于发送数千个带有不必要标记的模型实例的坏例子会起作用,在某些连接上它可能会非常慢,但它会起作用并且浏览器不会有任何抱怨的理由。 安德烈丹尼尔,感谢您的及时回复。 “raw-er”是针对本机应用程序的,而不是浏览器。关键是,与浏览器不同,它们也容忍非 HTML 显示方式。无论如何 - 很多人编写 Django。他们中的大多数——我假设——使用 ajax。将处理留给客户但仍不重复自己的最佳做法是什么?是否“正确”设计了您的 html 页面,以便插入某种“占位符”(在非 django 含义中)与动态数据一起插入?例如,如何支持“ajaxy”newsffed? 你好,安德烈丹尼尔。请查看我的帖子已更新,因为它是基于意见的。很想听听您对已编辑问题的意见。谢谢。【参考方案3】:

在服务器端渲染可能比在客户端更快。但是,它要求您的服务器具有更高的性能。

如果您已经在 django 中编写了模板,则可以通过返回完整的 html 数据来节省开发时间。否则你必须在 JS 中编写自己的渲染方法。

在这种情况下,如果您在 django 中更改任何内容,则必须在客户端代码上复制自己。

我个人认为在服务器上渲染更安全、更简单。

【讨论】:

【参考方案4】:

谢谢大家的回复。

我想更新一下,我决定采用优雅的解决方案,结果证明它更实用,这意味着让客户端完成工作:

我只将精简的 JSON 元素传输到客户端;我让客户端生成相关的HTML。

确实,这有点“重复”我自己,因为服务器端和客户端都有相似的代码段来处理完全相同的 HTML 段的创建。

尽管如此,我很清楚,在这种情况下,松散耦合对于能够扩展到其他非 PC 界面(如 android、ios、windows phone 等)至关重要。

此外 - 这样更快。当客户端可以做到时,无需为服务器端渲染无数的 HTML。

再次感谢大家。

我的结论是 - 做对了,即使看起来成本更高。

【讨论】:

以上是关于我应该在服务器端呈现 ajax 响应吗?的主要内容,如果未能解决你的问题,请参考以下文章

AJAX 响应可以设置 cookie 吗?

Ruby on Rails,json vs js ajax 响应

react + redux + saga +服务器端渲染+如何停止服务器端渲染页面的额外ajax调用?

jquery datatables添加带有ajax服务器端响应的复选框

ajax html响应中的AngularJs数据绑定

Ajax--服务端响应Json数据