为什么在 HTML 中使用 onClick() 是不好的做法?

IT技术 javascript html
2021-01-15 21:05:05

我多次听说onClick()在 HTML中使用 JavaScript 事件,例如, 是一种不好的做法,因为它不利于语义。我想知道缺点是什么以及如何修复以下代码?

<a href="#" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
6个回答

您可能在谈论不显眼的 Javascript,它看起来像这样:

<a href="#" id="someLink">link</a>

中央 javascript 文件中的逻辑如下所示:

$('#someLink').click(function(){
    popup('/map/', 300, 300, 'map'); 
    return false;
});

优点是

  • 行为(Javascript)与表示(HTML)分离
  • 没有语言混合
  • 您正在使用像 jQuery 这样的 javascript 框架,它可以为您处理大多数跨浏览器问题
  • 您可以一次向大量 HTML 元素添加行为而无需重复代码
本次讨论的另一点,与新手 -onclick可以更明确地映射元素交互和效果(函数调用)之间的因果关系,并减少认知负荷。许多课程让学习者陷入在addEventListener更困难的语法中包含更多想法的过程。此外,最近的基于组件的框架(如 Riot 和 React)使用了该onclick属性,并且正在改变分离应该是什么的概念。从 HTML 转移onclick到支持此功能的组件可能是一个更有效的学习“步骤”过程。
2021-03-23 21:05:05
@François Wahl:主要缺点是可发现性:查看 HTML 并不会告诉您附加了哪些回调,甚至不知道是否有任何回调。
2021-03-27 21:05:05
@MichaelBorgwardt:我完全同意你的看法,这是一个劣势。如果代码结构良好且组织良好,那么在处理项目或调试其他人的代码库时,我不认为这是一个大问题。总的来说,虽然我同意你的观点,但我不认为可发现性是编写内联脚本的一个很好的理由,牺牲代码可测试性和将函数/行为代码与 DOM 分离的能力等好处。我并不是说内嵌代码不好,不能工作。它确实并且绝对没问题,这取决于您是否对可测试性之类的事情感兴趣。
2021-04-02 21:05:05
你列出了很多优点,但缺点呢?调试冒蓝烟?
2021-04-06 21:05:05
@abelito:不确定调试是一个缺点。如果有的话,调试是一个优势,因为您可以在任何浏览器调试工具中单步调试 JavaScript。如果代码内嵌一个onClick. 如果您希望针对您的脚本,您也可以编写单元测试,如果代码在 an 内部onClick并且没有逻辑分离,我认为这也很难我个人对调试不显眼的 JavaScript 没有任何问题,管理和测试 JavaScript 代码的好处远远超过不使用它。
2021-04-08 21:05:05

如果您使用的是 jQuery,那么:

HTML:

 <a id="openMap" href="/map/">link</a>

JS:

$(document).ready(function() {
    $("#openMap").click(function(){
        popup('/map/', 300, 300, 'map');
        return false;
    });
});

这样做的好处是在没有 JS 的情况下仍然可以工作,或者如果用户中间单击链接。

这也意味着我可以通过再次重写来处理通用弹出窗口:

HTML:

 <a class="popup" href="/map/">link</a>

JS:

$(document).ready(function() {
    $(".popup").click(function(){
        popup($(this).attr("href"), 300, 300, 'map');
        return false;
    });
});

这将允许您通过为其提供弹出类来向任何链接添加弹出窗口。

这个想法可以进一步扩展,如下所示:

HTML:

 <a class="popup" data-width="300" data-height="300" href="/map/">link</a>

JS:

$(document).ready(function() {
    $(".popup").click(function(){
        popup($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');
        return false;
    });
});

我现在可以在整个网站上为大量弹出窗口使用相同的代码,而无需编写大量的 onclick 内容!是的,可重用性!

这也意味着,如果稍后我决定弹出窗口是不好的做法(它们是!)并且我想用灯箱样式的模态窗口替换它们,我可以更改:

popup($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');

myAmazingModalWindow($(this).attr("href"), $(this).data('width'), $(this).data('height'), 'map');

我整个网站上的所有弹出窗口现在都完全不同。我什至可以进行特征检测来决定在弹出窗口上做什么,或者存储用户偏好以允许与否。使用内联 onclick,这需要大量的复制和粘贴工作。

@Thomas Shields:不,他的意思是如果您没有 Javascript,该链接仍会将您带到 /map/...
2021-03-09 21:05:05
啊丰富!我们都爱你这个最漂亮的解决方案!
2021-03-10 21:05:05
没有 JavaScript 也能工作??它是 jQuery。它需要在浏览器上启用 Javascript 才能工作,对吗?
2021-03-20 21:05:05
是的,但在这种情况下,链接可以重定向到无需 JavaScript 即可执行操作的页面。
2021-03-24 21:05:05
链接无需 JavaScript。查看链接如何具有正常的 href 属性。如果用户没有 JavaScript,链接仍然是一个链接,用户仍然可以访问内容。
2021-03-29 21:05:05

它不好有几个原因:

  • 它混合了代码和标记
  • 以这种方式编写的代码通过 eval
  • 并在全局范围内运行

最简单的方法是为元素添加一个name属性<a>,然后您可以执行以下操作:

document.myelement.onclick = function() {
    window.popup('/map/', 300, 300, 'map');
    return false;
};

尽管现代最佳实践是使用id名称而不是名称,并且使用addEventListener()而不是使用,onclick因为这允许您将多个函数绑定到单个事件。

有人可以解释一下吗?“以这种方式编写的代码会通过 eval”……我在网上找不到任何关于此的信息。你是说使用内联 Javascript 有一些性能或安全方面的缺点吗?
2021-03-13 21:05:05
@preaction 就像内联事件处理程序一样,因此为什么我的回答说最好使用addEventListener(),以及为什么。
2021-03-15 21:05:05
即使建议这种方式也会让用户面临一系列事件处理程序冲突的问题。
2021-03-18 21:05:05

对于非常大的 JavaScript 应用程序,程序员使用更多的代码封装来避免污染全局范围。为了使 HTML 元素中的 onClick 操作可以使用一个函数,它必须在全局范围内。

你可能见过这样的 JS 文件...

(function(){
    ...[some code]
}());

这些是立即调用函数表达式 (IIFE),在其中声明的任何函数将仅存在于其内部范围内。

如果function doSomething(){}在 IIFE 中声明,然后doSomething()在 HTML 页面中执行元素的 onClick 操作,则会出现错误。

另一方面,如果您在该 IIFE 中为该元素创建一个 eventListener 并doSomething()在侦听器检测到单击事件时调用,则您很好,因为侦听器并doSomething()共享 IIFE 的范围。

对于代码量最少的小型网络应用程序,这无关紧要。但是,如果您渴望编写大型、可维护的代码库,onclick=""那么您应该努力避免这种习惯。

如果你渴望编写大型的、可维护的代码库,请使用 JS 框架,如 Angular、Vue、React……这些框架建议将事件处理程序绑定到它们的 HTML 模板中
2021-04-03 21:05:05

有几个原因:

  1. 我发现分离标记有助于维护,即 HTML 和客户端脚本。例如,jQuery可以轻松地以编程方式添加事件处理程序。

  2. 您提供的示例在任何不支持 javascript 或已关闭 javascript 的用户代理中都会被破坏。渐进增强的概念将鼓励/map/为没有 javascript 的用户代理创建一个简单的超链接,然后为支持 javascript 的用户代理以编程方式添加点击处理程序。

例如:

标记:

<a id="example" href="/map/">link</a>

Javascript:

$(document).ready(function(){

    $("#example").click(function(){
        popup('/map/', 300, 300, 'map');
        return false;
    });

})
感谢您提醒我渐进式增强,因此这仍然符合该范式: <a href="/map/" onclick="popup('/map/', 300, 300, 'map'); return false;">link</a>
2021-03-19 21:05:05