页面刷新后Local Storage表单数据被覆盖的技术求助
Squarespace表单LocalStorage数据持久化异常问题
我正在为Squarespace表单实现LocalStorage数据持久化功能,目标是在表单提交前保存所有字段数据,避免用户误关标签页或跳转时丢失数据。表单包含Text、Email、Text Area、Checkbox四种输入类型,每个输入都设置了自定义name属性,通过window.onload确保脚本在表单加载后执行。
目前会话期间能正常向localStorage的Form对象添加、更新数据,但页面刷新后,后续编辑或添加输入内容会导致之前的所有数据被清空。怀疑是数组键处理遗漏、setItem/getItem配置错误或React结构相关问题,尝试过一些方案但无效,也没找到Squarespace表单持久化的可用示例。
现有LocalStorage代码
$(window).on('load', function () { Name = document.getElementById('text-cc23c8ea-6327-4428-a14a-b3fb48c68303-field'); Email = document.getElementById('email-yui_3_17_2_1_1676942394006_15077-field'); Phone = document.getElementById('text-98fe5141-07c9-45c7-a3cf-3055be1b1f1c-field'); Company = document.getElementById('text-f5c0d7f9-0fb2-4533-95c0-11d9a232c96a-field'); Website = document.getElementById('text-040063da-dff1-41a6-8471-3e4cb7ebfd44-field'); Background = document.getElementById('textarea-73d1c76d-d63e-4f84-abad-de04a711eee5-field'); Requirements = document.getElementById('textarea-ed868b91-765d-4c42-9fc6-5943d50237b5-field'); Description = document.getElementById('textarea-ed868b91-765d-4c42-9fc6-5943d50237b5-field'); Service = document.querySelectorAll('input[type="checkbox"]'); let elems = Array.from(document.querySelectorAll('section[data-section-id="63f41c32be07cb3324ff12cf"] .react-form-contents input, section[data-section-id="63f41c32be07cb3324ff12cf"] .react-form-contents textarea')); elems.forEach(e => e.addEventListener('input', handleChange, false)); let cached = getForm(); if(cached) { Name.value = cached.Name; Email.value = cached.Email; Phone.value = cached.Phone; Company.value = cached.Company; Website.value = cached.Website; Background.value = cached.Background; Requirements.value = cached.Requirements; Description.value = cached.Description; if(cached.Service) { Service.forEach(c => { if(cached.Service.includes(c.value)) c.checked = true;}); }} document.querySelector('section[data-section-id="63f41c32be07cb3324ff12cf"] .react-form-contents').addEventListener('submit', () => { window.localStorage.removeItem('Form');}, false); function handleChange(e) { console.log('Form Update'); let Form = {}; Form.Name = Name.value; Form.Email = Email.value; Form.Phone = Phone.value; Form.Company = Company.value; Form.Website = Website.value; Form.Background = Background.value; Form.Requirements = Requirements.value; Form.Description = Description.value; Form.Service = []; Service.forEach(c => { if(c.checked) Form.Service.push(c.value); }); saveForm(Form);} function saveForm(Form) { let f = JSON.stringify(Form); window.localStorage.setItem('Form', f);} function getForm() { let f = window.localStorage.getItem('Form'); if(f) return JSON.parse(f);} });
问题原因及修复方案
核心问题
- 每次触发
handleChange时都创建全新的空Form对象,而非基于localStorage已缓存的数据更新。若刷新后DOM元素未被正确填充,新对象会将对应字段覆盖为空值。 Description和Requirements绑定了同一个DOM元素ID,导致两个字段数据互相覆盖。
修复步骤
修正重复的DOM元素绑定
找到Description对应的正确textarea元素ID,替换当前重复的ID:// 原错误代码 Requirements = document.getElementById('textarea-ed868b91-765d-4c42-9fc6-5943d50237b5-field'); Description = document.getElementById('textarea-ed868b91-765d-4c42-9fc6-5943d50237b5-field'); // 修正为各自正确的ID Requirements = document.getElementById('textarea-ed868b91-765d-4c42-9fc6-5943d50237b5-field'); Description = document.getElementById('textarea-【替换成正确的ID】-field');基于缓存数据更新Form对象
在handleChange中先获取缓存数据,再更新字段:function handleChange(e) { console.log('Form Update'); // 先获取缓存数据,无缓存则初始化空对象 let Form = getForm() || {}; // 逐个更新字段值 Form.Name = Name.value; Form.Email = Email.value; Form.Phone = Phone.value; Form.Company = Company.value; Form.Website = Website.value; Form.Background = Background.value; Form.Requirements = Requirements.value; Form.Description = Description.value; Form.Service = []; Service.forEach(c => { if(c.checked) Form.Service.push(c.value); }); saveForm(Form); }确保DOM元素完全加载
Squarespace表单基于React渲染,可改用DOMContentLoaded配合延迟检查,避免元素未挂载导致赋值失败:// 替换原window.onload document.addEventListener('DOMContentLoaded', function() { setTimeout(() => { // 原初始化代码放在此处 }, 1000); });
优化建议
- 避免硬编码元素ID:通过表单元素的
name属性选择元素,防止Squarespace自动生成的ID变化导致代码失效。 - 动态更新字段:根据触发事件的元素name属性更新对应Form字段,减少硬编码:
function handleChange(e) { let Form = getForm() || {}; const target = e.target; if(target.type === 'checkbox') { Form.Service = Array.from(Service).filter(c => c.checked).map(c => c.value); } else { // 需确保表单元素设置了正确的name属性 Form[target.name] = target.value; } saveForm(Form); }
内容的提问来源于stack exchange,提问作者Andy Quella
相关产品推荐
相关产品推荐

