提问人:haxxerz 提问时间:7/31/2012 最后编辑:Tibrogarganhaxxerz 更新时间:6/12/2023 访问量:6687
为什么内联事件处理程序属性在现代语义 HTML 中是一个坏主意?
Why are inline event handler attributes a bad idea in modern semantic HTML?
问:
内联事件处理程序是否被视为一种不好的做法?
例如:<button onclick=someFunction()>Click me!</button>
如果是这样,使用内联事件处理程序的缺点是什么?
答:
这是个坏主意,因为......
最佳实践建议在内容、风格和脚本之间明确划分。用内联 JavaScript(或 CSS)混淆 HTML 与此不一致。
例如,您只能将每种类型的一个事件(每个元素)与 -style events 绑定,因此您不能有两个事件处理程序。
on*
onclick
如果以内联方式指定事件,则 JS 将指定为字符串(属性值始终为字符串),并在事件触发时进行评估。评价是邪恶的。
由内联事件处理程序表示的函数必须是全局的(或者至少是全局可访问的),这在当今很少见;代码通常被命名空间化,或封装在模块中(感谢 Simon @Sebastian)。
你使用的任何内容安全策略 (CSP) 都必须(不明智地)扩展,以允许评估内联 JavaScript。
简而言之,通过专用 API 或通过 jQuery 或其他方式集中处理事件。addEventListener
[2021年编辑]
如今,响应式框架在一定程度上扭转了这一趋势;响应式框架中的事件通常被指定为属性,例如在 Vue 中:
<p v-on:click='foo'>Hello</p>
...其中 是当前组件的数据对象的方法。foo
但是,这不是真正的内联事件处理;请参阅@adnanmuttaleb的回答下@colin的评论。
评论
onClick="handler1() || handler2()....|| handlern()"
v-on:click
实际上不是一个属性。这是一个指令,在引擎盖下,它将使用 vuejs.org/v2/guide/events.html#Listening-to-EventsaddEventListener
on*
除了语义和公认的答案中表达的其他意见外,所有内联脚本都被视为漏洞和高安全风险。任何希望在现代浏览器上运行的网站都应该通过元属性或标头设置“内容安全策略”(CSP) 属性。
这样做与所有内联脚本和样式不兼容,除非明确允许将它们作为排除项。虽然 CSP 目标主要是防止持续的跨站点脚本 (xss) 威胁,其中内联脚本和样式是 xss 的向量,但它不是当前浏览器中的默认行为,但将来可能会更改。
评论
'unsafe-inline'
'unsafe-hashes'
script-src
建立在@Mitya答案的基础上。
在大多数现代 JS 库中,React、Vue,..内联事件处理程序被认为是惯用的,但@Mitya提到的大多数限制都消失了。作为案例研究,我们将查看 Vuejs 并将其与上面列出的点进行比较:
- 你可以有多个事件处理程序,请看这里
- 事件值(处理程序)不是普通字符串,而是 js 表达式,请看这里
onclick
- 全局范围问题根本不存在(因为你的代码将被 webpack 或其他工具翻译、最小化、重新打包)。
在我看来,内联事件处理程序主要增强了可读性,但意见可能会有所不同。
评论
addEventListener
评论