4

现在是社区维基!

我想先说清楚:这不是关于服务器端 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:看起来我们所有参与过这篇文章的人都有共同的想法;很高兴知道还有其他想法相似的人。现在去说服这些家伙;)谢谢大家。

4

5 回答 5

3

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

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

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

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

于 2010-05-17T07:27:21.083 回答
3

我能想到的两个最大的区别是:

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

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

于 2010-05-17T07:29:35.220 回答
1

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

简单的推理是您是 Javascript 既存在于服务器端页面上,也存在于单独的 Javascript 文件中(假设您完全使用 Javascript)。当一切都无处不在时,修复问题可能成为调试的噩梦。

如果您没有使用除了服务器端脚本生成的任何其他 Javascript,它可能会很好并且易于管理(忘记不显眼的运动所说的)。

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

<Rant>

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

大多数上游通信(客户端到服务器)已经只是数据交换,而不是下游通信。许多服务器端脚本生成 HTML,将其与数据合并并返回。只要服务器控制生成 HTML 视图就可以了。但是当花哨的 Javascript 出现并开始将行附加到表中,并通过精确复制现有的 HTML 结构来添加 div 的注释时,那么我们已经创建了生成标记的两个点。

$(".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>

除了语义和行为分离,我想说基本上归结为重复。您是否不必要地重复代码。是否有多个层处理相同的逻辑。是否可以将所有这些都推到一个层中,或者减少所有重复。

于 2010-05-17T07:57:47.987 回答
0

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

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

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

于 2010-05-17T08:02:13.630 回答
-1

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

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

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

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

于 2010-05-17T07:29:17.203 回答