向可能不在页面上的元素添加事件监听器?
2021-04-17
719
向页面上可能未出现的元素添加事件侦听器的最佳做法是什么?
例如,假设我们有一个出现在文章页面上的评论表单,并附加了
submit
事件侦听器。
document.getElementById('commentform').addEventListener('submit', event => {
/* do something */
})
此代码放置在站点模板的
script.js
文件中,该文件在每个页面上加载。但是,未出现评论表单的页面将导致错误:
Uncaught TypeError: Cannot read property 'addEventListener' of null...
我们如何防止发生此 TypeError?
2个回答
简单的方法是先检查元素是否存在...
const commentForm = document.getElementById('commentform');
if (commentForm) {
commentForm.addEventListener('submit', event => {
/* do something */
})
}
在现代环境中,您可以使用可选链:
document.getElementById('commentform')?.addEventListener('submit', event => {
/* do something */
})
但更好的方法是设置页面上的
commentform
与其相关脚本
完全连接
,这样就不会出现没有另一个的脚本。通常,人们会使用一个框架来实现这一点,将 commentform 的 HTML 与其提交监听器集成在一起。这是我推荐的专业方法。如果没有这个,您也可以将 commentform 的脚本放在 commentform 旁边:
<form id="commentform">
...
</form>
<script>
document.getElementById('commentform').addEventListener('submit', event => {
/* do something */
})
</script>
CertainPerformance
2021-04-17
不是最佳做法
正如 @CertainPerformance 所说,在生产代码中,您需要设置脚本加载,以便永远不会发生这种情况。但是,我在用户脚本环境中使用的一个技巧是使用 MutationObserver ,因为我对加载没有太多控制权。
window.addEventListener('load', function() {
let button = document.querySelector('.blahblahblah');
if (button) {
button.click();
console.log('Button found early');
}
// This waits to run until ".somerootelement" has changed
let mo = new MutationObserver(function() {
document.querySelector('.blahblahblah').click();
console.log('Button found late');
});
mo.observe(document.querySelector('.somerootelement'), { childList: true });
});
但我想说 90% 的时间这是一种反模式。当然,如果您可以更改脚本加载,以便依赖项正确加载。
xdhmoore
2021-04-17