添加购物车按钮EventListener后,form调用preventDefault()仍提交问题
问题根源
你代码里的核心问题是重复赋值window.onload:第一次把表单处理函数赋值给window.onload,但随后在setTimeout里又把window.onload替换成了购物车按钮的处理函数。这导致页面加载完成后,只有购物车的逻辑被执行,表单的submit事件监听根本没被注册,event.preventDefault()自然起不到作用,表单会按默认行为提交跳转。
修复方案
方案1:合并逻辑+事件委托(推荐)
把两个逻辑放到同一个window.onload里,同时用事件委托替代setTimeout处理动态按钮,避免依赖不可靠的超时等待:
window.onload = function() { // 处理表单提交 const form = document.getElementById('login-form'); form.addEventListener('submit', event => { event.preventDefault(); const username = form.elements.username.value; const password = form.elements.password.value; login(username, password); }); // 事件委托处理动态添加的购物车按钮 document.addEventListener('click', event => { if (event.target.classList.contains('purchase-button')) { const btn = event.target; // 用find替代for in循环,更简洁安全 const product_selected = products.find(product => product.id === btn.dataset.productId); addToCart(product_selected); } }); };
方案2:分开注册load事件
如果要保留逻辑分离,不要直接赋值window.onload,而是用addEventListener注册多个load事件:
// 注册表单处理逻辑 window.addEventListener('load', function() { const form = document.getElementById('login-form'); form.addEventListener('submit', event => { event.preventDefault(); const username = form.elements.username.value; const password = form.elements.password.value; login(username, password); }); }); // 注册购物车按钮处理逻辑(事件委托) window.addEventListener('load', function() { document.addEventListener('click', event => { if (event.target.matches('.purchase-button')) { const btn = event.target; const product_selected = products.find(p => p.id == btn.dataset.productId); addToCart(product_selected); } }); });
额外优化点
- 用
Array.find()替代for...in循环查找商品,代码更简洁且避免遍历对象原型链的问题; - 事件委托不需要等待动态元素加载完成,只要元素存在于页面中时触发点击,就能被捕获处理,比
setTimeout更稳定可靠。
内容的提问来源于stack exchange,提问作者hadrianstav
相关产品推荐
相关产品推荐

