在服务器端级别渲染javascript。好主意还是坏主意?

时间:2010-05-17 07:04:15

标签: asp.net javascript jquery server-side serverside-javascript

现在是社区维基!

我想首先说清楚:这不是与服务器端Javascript或运行Javascript服务器端相关的问题。这是一个关于从服务器端代码呈现Javascript代码(将在客户端执行)的问题。

话虽如此,请看下面的ASP.net代码:

hlRemoveCategory.Attributes.Add("onclick", "return confirm('Are you sure you want to delete this?');")

这是在服务器端规定客户端onclick事件。

反对在客户端编写Javascript:

$('a[rel=remove]').bind('click', function(event) {
    return confirm('Are you sure you want to delete this?');
}

现在我想问的问题是从服务器端代码渲染javascript有什么好处?或反之亦然?

我个人更喜欢将客户端UI /行为挂钩到HTML元素的第二种方式,原因如下:

  • 服务器端执行它已经需要的任务,包括数据验证,事件委托等;和
  • 服务器端看到的事件不一定是客户端的相同过程。也就是说,客户端还有更多的事件(只看自定义事件);和
  • 在客户端和服务器端发生的事情,在一个事件中,可能完全不相关和解耦;和
  • 在客户端发生的事情发生在客户端,没有需要供服务器知道。服务器应该处理并运行给予它们的内容,如果客户端事件发生,那么进程如何生效并不是由他们决定的;等等。

这些是我的想法显然是。我想知道其他人的想法以及是否有关于这个主题的讨论。

从此参数分支的主题可以达到:

  • 代码管理:从服务器端渲染所有内容是否更容易?
  • 关注点分离:如果将客户端逻辑分离到服务器端逻辑,会更容易吗?
  • 效率:在编码和运行方面效率更高?

在一天结束时,我试图让我的团队转向第二种方法。这支球队中有很多老球员都害怕这种变化。我只想用正确的事实和统计数据说服他们。

让我知道你的想法。

UPDATE1:看起来我们所有参与此帖的人都有共同的想法;很高兴知道其他人也有同样的想法。现在要说服这些人;)谢谢大家。

5 个答案:

答案 0 :(得分:3)

你的第二个例子远远优于第一个例子。 Javascript是您的行为层,应该与您的语义标记(内容)和CSS(演示文稿)分开。这是更好的架构有很多原因:

  • 鼓励逐步提升。正如您所提到的,后端代码应该在没有JS的情况下正常工作。您不能依赖拥有JS的客户。这样你可以在没有JS的情况下构建一次,然后可以增强那些使用JS的人的体验(例如通过添加客户端验证以及服务器端验证,以便客户端可以获得即时反馈)
  • 清洁标记。通常会减少下载大小。一个单独的JS文件中的一个可重用选择器,可以在页面之间缓存和共享,而不是每个元素上的处理程序。
  • 你所有的JS都在一个重复使用的地方。例如如果您的代码打开了一个弹出窗口并且您决定更改窗口的尺寸,您将在JS文件的代码中更改它一次,而不必在每个内联处理程序中更改它。

还有很多其他论点和理由,但它们应该让你开始......

另外,从您的示例中可以看出,您的文档中有一个可以删除内容的普通链接。这也是一种不好的做法。删除或更新内容的任何内容都应该在POST(而不是GET)请求上完成。所以它应该是提交表格的结果。否则例如googlebot可能会通过抓取您的网页而意外删除您的所有内容(并且搜索引擎机器人不执行JS,因此您的警报无法帮助)

答案 1 :(得分:3)

我预先想到的两个最大的差异是:

  • 如果javascript位于单独的js文件中,您将失去客户端缓存
  • 如果你需要更改你的javascript,你必须重新编译(推断这是你发布产品后会发生的事情:如果你必须重新编译,那么你需要重新分配二进制文件而不仅仅是一个修改过的js文件)
  • 如果javascript位于单独的文件中,则更容易使用VS调试器;您可以在该文件中设置断点,如果您要生成代码服务器端,则必须使用正在运行的文档功能,找到生成的代码然后添加断点,并且每次重新启动时都必须手动添加该断点 - 运行你的应用程序。接下来,如果代码在一个单独的文件中,那么你可以调整javascript代码,F5你的浏览器页面,并继续调试而不必停止并重新启动调试器。

应该提到的是,有时您必须从服务器插入js代码 - 例如,如果您的大部分代码都在一个单独的js文件中,并且您需要将控件标识插入页面以使该代码可以使用。如果可能的话,尽量避免这种情况。

答案 2 :(得分:1)

看起来你已经知道该怎么做了。在服务器端渲染它是个坏主意。

简单的推理是你是Javascript既存在于服务器端页面,也存在于单独的Javascript文件中(假设您使用的是Javascript)。当一切无处不在时,它可以成为调试噩梦。

除了服务器端脚本生成的内容之外,你没有使用任何其他Javascript,它可能会很好并且易于管理(忘记那些不引人注目的运动)。

其次,如果页面上有100个链接,您将在100个地方重复相同的代码。重复是另一个维护和调试的噩梦。您可以使用一个事件处理程序和一个属性处理所有页面上的所有链接。这甚至不需要再考虑一下。

<Rant>

分离HTML和Javascript并不容易,甚至CSS,尤其是如果你想要一些AJAX或UI的好处。为了实现完全分离,我们必须转移到桌面应用程序模型,其中所有前端代码都是在客户端使用Javascript以编程方式生成,并且所有与服务器仅限于纯数据交换。

大多数上游通信(客户端到服务器)已经只是数据交换,而不是下游通信。许多服务器端脚本生成HTML,将其与数据合并并将其吐回。只要服务器保持生成HTML视图的命令,这就没问题。但是当花哨的Javascript出现在板上并开始向表中添加行,并通过复制现有的HTML结构来完成注释时,我们创建了两个生成标记的点。

$(".comments").append($("<div>", {
    "id": "123",
    "class": "comment",
    "html": "I would argue this is still bad practice..."
}));

也许这不是一场噩梦(取决于规模),但它也可能是一个严重的问题。现在,如果我们更改注释的结构,则需要在两个位置完成更改 - 服务器端脚本和最初生成内容的模板,以及在页面加载后动态添加注释的Javascript端。

第二个示例是关于使用拖动和拖动的应用程序。如果您可以在页面上拖动div,则需要将它们从常规页面流中取出,并使用精确坐标绝对或相对定位。既然我们不能事先为所有可能的坐标创建类(并且尝试是愚蠢的),我们基本上直接在元素中注入样式。然后我们的HTML看起来像:

<div style="position: absolute; top: 100px; left: 250px;">..</div>

我们搞砸了美丽的语义页面,但必须这样做。

</Rant>

除了语义和行为分离之外,我想说的基本上归结为重复。你是否不必要地重复代码。多个层是否处理相同的逻辑。是否有可能将其全部推入单层,或减少所有重复。

答案 3 :(得分:0)

您和其他回答此问题的人已经列出了为什么最好不要让服务器端代码将内部事件属性吐入文档中的原因。

硬币的另一面是,快速简单(至少在短期内)。

IMO,这并没有超过方法的缺点,但这是一个原因。

答案 4 :(得分:-1)

对于您示例中的代码,它并不重要。代码不使用仅在服务器端可用的任何信息,因此在客户端代码中绑定事件同样容易。

有时您希望使用服务器端可用的某些信息来决定是否应添加事件,或者为事件创建代码,例如:

if (categoryCanBeDeleted) {
  hlRemoveCategory.Attributes.Add(
    "onclick",
    "return confirm('Are you sure you want to delete the " + categoryType + "?');"
  );
}

如果您要在客户端执行此操作,则必须以某种方式将此信息放入页面中,以便客户端代码也可以访问它。