JavaScript如何通用更新深层复杂Map对象实现点赞状态切换
嵌套Map状态通用点赞功能实现
数据结构约定
先对齐通用的状态结构,可根据你的实际字段做适配:
// state 根结构:Map<userId: string, userContent: Object> // 单个userContent结构 { posts: Array<{ id: string, // 对应contentType为post时的contentId isLiked: boolean, totalLikes: number, comments: Object<commentId: string, { // 评论对象,key为评论ID id: string, isLiked: boolean, totalLikes: number }>, // 其他自定义帖子字段不影响逻辑 }>, // 其他自定义用户字段不影响逻辑 }
完整实现代码
function like(state, contentOwnerId, contentType, contentId, commentId) { // 目标用户不存在直接返回拷贝后的原state const userContent = state.get(contentOwnerId) if (!userContent) return new Map(state) // 浅拷贝用户内容,避免修改原数据 const newUserContent = {...userContent} newUserContent.posts = [...newUserContent.posts] // 查找目标帖子 const postIndex = newUserContent.posts.findIndex(post => post.id === contentId) if (postIndex === -1) return new Map(state) // 浅拷贝目标帖子 const targetPost = {...newUserContent.posts[postIndex]} newUserContent.posts[postIndex] = targetPost if (contentType === 'post') { // 处理帖子点赞状态切换 const newIsLiked = !targetPost.isLiked targetPost.isLiked = newIsLiked targetPost.totalLikes = newIsLiked ? targetPost.totalLikes + 1 : targetPost.totalLikes - 1 } else if (contentType === 'comment') { // 校验评论参数合法性 if (!commentId || !targetPost.comments[commentId]) return new Map(state) // 浅拷贝评论对象 targetPost.comments = {...targetPost.comments} const targetComment = {...targetPost.comments[commentId]} targetPost.comments[commentId] = targetComment // 切换评论点赞状态 const newIsLiked = !targetComment.isLiked targetComment.isLiked = newIsLiked targetComment.totalLikes = newIsLiked ? targetComment.totalLikes + 1 : targetComment.totalLikes - 1 } else { // 不支持的内容类型直接返回原state return new Map(state) } // 生成全新Map实例,仅更新对应用户的内容 const newState = new Map(state) newState.set(contentOwnerId, newUserContent) return newState }
逻辑说明
- 所有更新操作遵循不可变原则,只拷贝修改链路的节点,未修改的节点复用原对象引用,兼顾性能和数据不可变要求
- 入参非法(目标用户/帖子/评论不存在、contentType不支持)时直接返回拷贝后的原state,避免错误修改
- 自动处理点赞/取消点赞两种场景的
isLiked和totalLikes联动更新 - 如果你的评论存储用的是Map而非普通对象,只需要把
targetPost.comments = {...targetPost.comments}改成targetPost.comments = new Map(targetPost.comments),取值/赋值逻辑对应换成Map的get/set方法即可 - 最终返回的是全新的Map实例,完全不会修改原state数据
内容的提问来源于stack exchange,提问作者Raul
相关产品推荐
相关产品推荐

