从零开始HTML实现收货地址管理页面
纯 HTML + JS 实现可增删改的收货地址列表 先说几个核心判断:纯静态 HTML 本身没法持久存地址,必须靠 JavaScript 操作 DOM,才能做出“看起来能用的”管理界面。核心思路是把地址数据存进 localStorage 里,每次加载页面时读出来渲染,所有增删改操作都要同步更新这个存
纯 HTML + JS 实现可增删改的收货地址列表
先说几个核心判断:纯静态 HTML 本身没法持久存地址,必须靠 JavaScript 操作 DOM,才能做出“看起来能用的”管理界面。核心思路是把地址数据存进 localStorage 里,每次加载页面时读出来渲染,所有增删改操作都要同步更新这个存储。
很多人容易踩的坑是:直接用 document.write 或者反复 innerHTML = ... 全量重写列表。这么做的后果是——丢掉已输入的表单焦点、清空未提交的编辑状态。正确的做法是:用 appendChild 和 removeChild 做增量操作,编辑时复用已有的 元素,而不是每次都重新造一套 DOM。
具体来说,有几个关键点需要注意:
- 地址数据建议用数组存,每一项是一个对象:
{ id: 'addr_1', name: '张三', phone: '138****1234', address: '北京市朝阳区xxx' }。这样结构清晰,后期扩展也方便。 - 新增时,ID 就取当前时间戳拼个前缀,比如
'addr_' + Date.now(),保证不重复。千万别用自增序号,删掉一条地址再新增时容易乱套。 - 编辑的逻辑是这样:点击“编辑”按钮后,把当前地址字段填入表单,同时把提交按钮的文字改成“更新”,再存一个临时变量
editingId记录当前在改谁。 - 提交时先判断
editingId有没有值:有的话,找到对应项直接替换;没有的话,用push把新地址塞进数组。逻辑简单,但胜在稳定。

为什么不能只靠 form 提交就完事了
因为没有后端接收数据, 默认提交行为会直接刷新页面——你刚填好的地址瞬间就没了。所以关键一步是:在 submit 事件里调用 event.preventDefault() 把页面刷新拦下来。
另一个很容易忽略的问题是:表单校验确实写在 submit 事件里了,但如果没有返回 false,哪怕弹了 alert,只要没阻止默认行为,页面照样刷新。更稳妥的做法是:校验失败时直接 return false,成功才继续执行后续逻辑。
关于校验,几个细节值得注意:
- 手机号校验不能只看长度,至少要加个
/^1[3-9]\d{9}$/.test(phone),排除掉那些明显不合法的号段。 - 姓名和地址为空时要给出提示,但别用
alert中断流程——用户体验太差。改用做内联提示,更友好。 - 所有输入框加上
required属性只是基础,真正生效的环节在 JS 校验这里,这两者不能互相替代。
localStorage 存地址,要注意哪些细节
localStorage 只能存字符串。如果你直接写 localStorage.setItem('addresses', addresses),存进去的会变成 [object Object],[object Object] 这种无意义的东西。必须用 JSON.stringify() 序列化后再存,读取时用 JSON.parse() 还原。
但容易被忽略的是——JSON.parse() 这步其实会抛错。比如用户手动清空了 localStorage 里的值,或者存了非法的 JSON 格式,一解析就直接崩溃。所以必须包在 try...catch 里,出错时回退到空数组。
let addresses = [];
try {
const saved = localStorage.getItem('addresses');
if (saved) addresses = JSON.parse(saved);
} catch (e) {
console.warn('地址数据解析失败,使用空列表');
}
另外,每次修改数据后要立刻调用 localStorage.setItem('addresses', JSON.stringify(addresses)) 写回存储。别想着攒到页面卸载时再统一存——beforeunload 事件在不少浏览器里并不可靠,用户一关标签页数据就丢了。
还有一个兼容性问题:浏览器开启隐私模式时,localStorage 可能被禁用。这种情况需要做降级处理,比如 fallback 到内存变量,至少保证页面内操作不崩溃。
“设为默认地址”功能,怎么才能真正生效
所谓“默认”,其实就是给某条地址加一个 isDefault: true 字段,同时保证整个数组里最多只有一个 true。每次点击“设为默认”按钮时,先遍历数组把所有地址的 isDefault 都设为 false,再把当前点击的那条设为 true,最后存回 localStorage。
渲染列表时,根据 address.isDefault 的值决定是否显示“(默认)”标签以及是否加高亮样式。提交新地址时,isDefault 默认设为 false,除非用户勾选了“设为默认”的复选框。
几个实操上的细节:
- DOM 上的“设为默认”按钮建议用
data-id="addr_123"来携带目标 ID,这样事件绑定更清晰,不依赖 DOM 顺序。 - 如果页面里有多条地址块,每个块的“设为默认”按钮要绑定独立的事件处理器,或者用事件委托来覆盖动态添加的项,别漏掉。
- 编辑已有地址时,要保留原来的
isDefault状态,除非用户主动在编辑表单里修改了这项。
真实项目里,地址管理很快会遇到多地址类型(公司/家庭/学校)、省市区三级联动、地址自动补全这些问题。但回到“从零开始”这个出发点,先把 localStorage 的读写闭环、DOM 增量更新、表单防刷新这三件事做扎实了,后面的扩展才有稳固的基础。
