【问题标题】:Why is separation of JavaScript and HTML a good practice? [closed]为什么分离 JavaScript 和 HTML 是一种好的做法? [关闭]
【发布时间】:2015-06-08 13:08:31
【问题描述】:

我一直在阅读有关 JavaScript 的一些好的做法,其中之一是 Unobtrusive JavaScript。第一点引起了我的注意

将功能(“行为层”)与网页的结构/内容和表示分离

在 wiki 页面上,其中一个示例是您应该将操作绑定到 JS 文件中的事件,而不是 HTML 中的事件。这个例子

<input type="text" name="date" id="date" />
...
window.onload = function() {
    document.getElementById('date').onchange = validateDate;
};

优于

<input type="text" name="date" onchange="validateDate()" />

但是,我会说我更喜欢带有onchange 属性的第二个代码而不是第一个。我这样做的原因是

  • 它易于阅读并立即清楚该元素的更改(或任何其他事件)会发生什么。
  • 我不必通过 JavaScript 文件查看 onchange 事件在哪里(以及是否)绑定,以及是否有一些其他事件,例如为 #date 定义的 click
  • AngularJS 等框架具有ng-click,并且正在将 HTML 结构与 JS 混合。为什么我不应该?

我读过的不使用不显眼的 javascript 的缺点是

  • 污染全局命名空间。
  • 创建冗长且不可读的内联代码。
  • 如果事件的代码发生变化,您只需在一处进行更改 - 即在 JS 文件中。

但我认为缺点是可以解决的。

  • 不要污染命名空间,而是在一个变量中创建应用程序,使代码看起来像 onchange="app.validateDate()" 并且不会发生污染。
  • 内联代码不会被写入,而是在 JS 文件中的一个函数中分离,然后像 onclick="app.action();" 一样调用它。
  • 不就是在onclick属性中使用函数吗?因为最终您必须在两种方法中仅对一个函数进行更改,无论是$('input').change(function () {/* ... change ... */}); 还是app.action = function () {/* ... change ... */}

那么它实际上仍然被认为是一种好的做法吗?

【问题讨论】:

  • 我们将其分开的主要原因是因为这样,将来进行更改会容易得多。您不想更改 onChange 函数的名称,然后让 tyo 浏览所有 HTML 来更改它。您还希望人们能够在没有 javascript 的情况下使用您的网站,因此仅在有 javascript 的情况下将他们绑定是一种很好的做法。它还使您的代码更简单,因为您将所有内容分开。就像外部 CSS 文件更容易一样,您可以交换文件来更改样式,交换 JS 文件可以让您在交互方面做同样的事情。
  • 此外,并非所有浏览器都为所有元素实现相同的事件。例如,您可能有特定于浏览器的实现。
  • 最后,这也是一种很好的做法,因为它是常见的做法。任何其他开发人员会使用您的代码吗?他们知道会发生什么。这在很大程度上是一个约定。另请参阅:'第三,代码更像是您所说的“指南”,而不是实际规则。欢迎登机。' - 巴博萨船长
  • 关于一致性,有些事情只有从JS代码中附加事件才能实现。因此,您将有两种处理事件的方法,一种将它们定义为属性,另一种将它们从 JS 代码附加 - 当您稍后尝试阅读代码和代码的一般设计时,不一致是很糟糕的。
  • 虽然我同意第二个代码更短并且可能更好,但将 JavaScript 与 HTML 分开是更好的做法。想象一下,你在一个团队中工作,你只负责 JavaScript 编程。创建和编辑 HTML 文件的是其他人。还有其他人关心 CSS。通过分离关注点,每个团队都可以专注于自己的部分,而不会干涉其他团队的事务。

标签: javascript html angularjs


【解决方案1】:

这是一个非常广泛的主题,并且很大程度上基于意见。对所有事情都没有唯一的答案。但是,这里有一些观察:

  1. 无论你做什么,你都在污染命名空间。 app.validateDate 就像 validateDate 一样污染命名空间,只是因为需要有一个全局可访问的函数名。在复杂的现代网站中,有大量脚本争夺全球名称。理想情况下,您永远不会在全局范围内公开任何名称,甚至是命名空间名称。

  2. .onclick = handler 也不是很好。你想要:

    document.getElementById('date').addEventListener('change', function () { .. });
    

    更不显眼,并允许多个脚本将事件侦听器绑定到同一个元素。同样,在复杂的现代站点中,您可以拥有的最高优先级之一是确保没有人踩到其他人的脚。您永远不知道将来还有谁可能对该元素的change 事件感兴趣。

  3. 与其他地方相比,内联编写它更多的代码。更长的 HTML 代码。 HTML 可能已经非常冗长了。任何你可以移动到你应该移动的地方。减少任何特定文件中的代码量本身就是一门艺术,对可读性很重要。是的,它“只是多了一个属性”......在所有其他属性和元素以及您也没有避免的内联声明之上。它只是堆积起来,这就是代码变得混乱、不可读和不可维护的原因。

  4. 可重用性:document.getElementById(..).addEventListener 可以在外部文件中写入一次,并在许多不同的页面中自动重用。 &lt;.. onclick=".."&gt; 每次都需要重复写入。干燥你的代码。

对于小型项目,这通常并不重要。但同样,网站变得越来越复杂。业务需求需要不断变化。再多一个分析脚本,再多一个基于 Javascript 的社交小部件,现在全部改回来,现在保持所有版本的依赖项同步,现在再次将其全部删除,并为下周发布的 2.0 重新设计。与其他 10 个人并行完成所有工作,而无需在每次构建时都互相攻击代码,也无需长时间解决 git-merge 冲突。在这样的环境中,每一点解耦、间接和灵活性都会有所帮助。

既然你提到了 Angular:

Angular 通过使用完全不同的模板解析模型来避免其中的一些问题。当你写onclick=foo时,你需要绑定一个全局函数名。但是,当 Angular 执行 ng-click=foo 时,foo 是 ng 范围内的本地范围实体。这不是一个全球名称。 Angular 将控制器和视图分开,控制器本质上在 $scope 对象上公开了视图可以使用的特定 API;只要保持指定的 API 协定,控制器和视图仍然可以互换(意味着只要 $scope 对象保持相同的属性)。

所有ng 指令都根据自定义范围和评估引擎进行评估,该引擎与 Javascript 的默认操作方式没有太大关系。

【讨论】:

  • 我意识到这是一个宽泛的话题,我并不是在寻找一个答案,我想听听其他意见,并且实际上看到了一些我不应该使用 HTML 属性的原因。您在答案中提到了好点,所以感谢您抽出时间和解释!
猜你喜欢
  • 2011-05-14
  • 2010-09-26
  • 2015-06-21
  • 2022-01-22
  • 2017-05-08
  • 1970-01-01
  • 1970-01-01
  • 2023-01-05
  • 1970-01-01
相关资源
最近更新 更多