json.stringify()存对象后读出是字符串,因localstorage只支持字符串存储且读取时未用json.parse()还原;新增联系人须用crypto.randomuuid()生成唯一id并检查重复;删除或修改后需及时存回localstorage并确保视图同步更新。

为什么 JSON.stringify() 存对象后读出来是字符串而不是对象
因为 localStorage 只支持字符串存储,JSON.stringify() 把对象转成字符串存进去了,但读取时没用 JSON.parse() 还原,直接当字符串用了——这是最常卡住的一步。
- 存的时候必须:
localStorage.setItem('contacts', JSON.stringify(contactsArray)) - 读的时候必须:
const contacts = JSON.parse(localStorage.getItem('contacts') || '[]')(注意加空数组兜底,否则getItem返回null会导致JSON.parse(null)报错) - 如果忘记
JSON.parse,后续调用contacts.push就会报TypeError: contacts.push is not a function - 别用
toString()或强制类型转换代替JSON.parse,那只会得到[object Object]
新增联系人时如何避免重复 ID 冲突
ID 不该靠用户输,也不该用 Date.now() 简单拼接——高并发或快速连点下可能撞车;更不能用数组索引当 ID,删过人之后索引就乱了。
- 推荐用
crypto.randomUUID()(现代浏览器):id: crypto.randomUUID(),唯一性有保障 - 兼容旧环境可改用时间戳 + 随机数:
id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}` - 存之前先检查是否已存在同 ID:
contacts.some(c => c.id === newContact.id),虽然概率极低,但写上不费事 - 别把 ID 存成数字类型(比如
123),JSON.stringify后再parse会保持为数字,但和字符串 ID 混用容易引发===判等失败
localStorage 里删联系人后数组长度对不上怎么办
常见错误是用 splice 或 filter 处理完没重新存回 localStorage,或者存了但读取逻辑没同步更新——看起来“删了”,其实只是内存里删了,下次刷新又回来。
- 删完必须立刻存:
localStorage.setItem('contacts', JSON.stringify(updatedContacts)) - 别在删除函数里只操作局部变量,要确保操作的是从
localStorage读出并解析后的那个数组引用 - 如果用
filter,记得赋值给新变量或原地替换:contacts = contacts.filter(c => c.id !== id),再存 - 调试时可在控制台手动执行
JSON.parse(localStorage.getItem('contacts'))确认内容是否真实更新
修改联系人姓名/电话后页面没变,但 localStorage 里数据却变了
这是典型的「状态没驱动视图更新」问题:你改了数组里某个对象的属性,但 Vue/React 没监听到深层变化,或者你用的是纯 JS 手动渲染,但 DOM 更新逻辑漏掉了对应节点。
- 纯 JS 场景下,改完数据后必须显式重绘列表:
renderContacts(contacts),不能只改数组 - 如果用
contacts.find(c => c.id === id).name = newName,记得之后调用localStorage.setItem,否则改的只是内存副本 - 避免直接改对象属性后不触发重新渲染——比如用
Object.assign或展开运算符生成新对象更安全:contacts = contacts.map(c => c.id === id ? { ...c, name: newName } : c) - 注意
localStorage的 5MB 上限,单个联系人字段别塞大段富文本或 base64 图片,否则存到一半静默失败
真正麻烦的不是序列化本身,而是每次读写都得在字符串和对象之间来回跳,稍一漏掉 parse 或 stringify,整个链路就断在看不见的地方。










