SPA切换登录路由提交表单时触发Cannot read properties of null错误
问题分析与解决方案
错误原因
你遇到的Cannot read properties of null (reading 'addEventListener')错误,核心问题出在时机不匹配:
- 首页的脚本在页面初始加载时就执行了
document.querySelector("#userinfo"),但此时登录页的表单还未被加载到DOM中,导致form变量为null,调用addEventListener直接报错。 - 就算后续切换到登录路由、表单成功加载,这段绑定事件的代码也不会重新执行,所以表单提交时监听器完全没触发。
解决方案
方案一:事件委托(推荐)
利用事件冒泡机制,把监听器绑定到页面始终存在的父元素(比如#main-page)上,不管表单什么时候加载,提交事件都会被捕获。
修改首页的脚本部分:
<script> async function sendData(event) { event.preventDefault(); console.log("I'm here 2"); const outputElement = document.getElementById('output'); outputElement.innerHTML = "change success"; } // 绑定到持久存在的父元素,监听表单提交事件 document.getElementById('main-page').addEventListener("submit", (event) => { // 仅处理#userinfo表单的提交 if (event.target.id === 'userinfo') { sendData(event); } }); </script>
这种方式无需关心页面切换时机,一次绑定即可覆盖所有后续加载的表单,通用性更强。
方案二:路由加载完成后绑定事件
在路由的页面渲染逻辑中,判断当前路径为登录页时,再动态绑定表单事件。
修改router.js中的handleLocation函数:
const handleLocation = async () => { const path = window.location.pathname; const route = routes[path] || routes[404]; const html = await fetch(route).then((data) => data.text()); document.getElementById("main-page").innerHTML = html; // 仅在登录页加载完成后绑定表单事件 if (path === '/login') { const form = document.querySelector("#userinfo"); async function sendData(event) { event.preventDefault(); console.log("I'm here 2"); const outputElement = document.getElementById('output'); outputElement.innerHTML = "change success"; } form.addEventListener("submit", sendData); } };
同时删除首页中原有的表单绑定脚本,避免初始加载时的报错和重复绑定问题。
内容的提问来源于stack exchange,提问作者John Sall
相关产品推荐
相关产品推荐

