🦖我是Sam9029,一个前端
Sam9029的掘金主页:Sam9029的掘金主页
**🐱🐉🐱🐉恭喜你,若此文你认为写的不错,不要吝啬你的赞扬,求收藏,求评论,求一个大大的赞!👍**
今日本想说些啥,想想无事,便不说些啥了,话不多说,直接上活
🐉源码实现
展示地址:Vue3小项目–评论列表 - 码上掘金 (juejin.cn)
效果展示:
🐉需求
- 一级评论创建
- 二级评论创建并关联一级评论
- 二级评论的可控制展开与否
- 评论时间戳-排序- (UNfinished)
全为本地数据操作
🐉
源数据
和接下来要创建的
整合对象
格式皆为 数组包对象;
[{},{},……]
源数据中
一级评论与二级评论 都在对象的同一属性层级(且有对应的不同id) - 例子- 二级通过 parent_id 来关联 一级评论
[{id:1,nick_name:"冬天的雨",content:"非常好的文章!",parent_id:0,time:1625454585,boolChild:false},{id:16,nick_name:"用户9527",content:"收藏饿了",parent_id:1,time:1625454733,boolChild:false},
……
]
🐉整体思路
🦊DOM 同一控制 评论item 以及 评论item
HTML+CSS
样式
- 所有的 评论item 都可以单独的作为一个 对象来考虑
- 同理 新建评论的 输入框 也是一样
🦊根据原始数据 - 创建
新对象数组--整合对象
为什么创建
整合对象
- 便于渲染 评论列表
- 介于评论 可以分为 一级 与 二级
- 若有一个对象(整合对象) 同时包含 一二级的评论内容,即可放别统一管理相关联的一二级评论
- 同时 用数组 来存储 所有的 对象(整合对象)
- 同时要具备 响应式
实现
- 通过侦听器(深度加立即侦听) 操作筛选 整合对象(
对象
) 以下内容- 引入 nanoid 给每个整合对象 唯一id- 一级评论 parent (对象
) - 一级评论唯一- 二级评论 child (数组
) - 可能有多个- 展开二级评论 控制 isShowChild(布尔值,默认值false
) - 控制 二级评论的 回复展示
- 整合对象
json
结构如下:[{itemId:''parent:{},chlid:[{},{}],isShowChild:false}, ……… ]
使用函数(
updateCommentData
)来 创建新的
整合对象
- 使用 update 意在更新,因为源数据可评论增加后会改变,单纯用创建来命名函数不太好
- 同时可被监听器调用
源码
// 被渲染的数据 及`整合对象`let renderData =ref()functionupdateCommentData(){// 深拷贝 消除 影响源数据let deepCloneOriginData =JSON.parse(JSON.stringify(originCommentListData.data))// 筛出 一级评论let parentData = deepCloneOriginData.filter(item=> item.parent_id ===0)// 筛出 二级评论let childData = deepCloneOriginData.filter(item=> item.parent_id !==0)let newRenderData =[]for(let i =0; i < parentData.length; i++){
newRenderData.push({// 使用nanoiditemId:parentData[i].id,//parent为对象,且只有一个层级属性 使用浅拷贝parent:{...parentData[i]},//parent为数组包对象,有两个层级属性 使用深拷贝child:JSON.parse(JSON.stringify(childData.filter(item=>item.parent_id===parentData[i].id))),isShowChild:false})}//
renderData.value =JSON.parse(JSON.stringify(newRenderData))// 测试输出// console.log(JSON.parse(JSON.stringify(renderData.value))) // 返回筛出数据 return 此场景可有可无return newRenderData
}
关键解析:
- 使用一级评论的id 作为 新的对象的id
itemId:parentData[i].id
- parent为对象,且只有一个层级属性 使用浅拷贝 parent: {…parentData[i]},
- parent为数组包对象,有两个层级属性 使用深拷贝 child: JSON.parse(JSON.stringify(childData.filter(item=>item.parent_id===parentData[i].id))),
- 展开二级评论 控制 isShowChild:false
侦听的实时更新变化数据
- 源数据定义在reactive 的 对象的属性data中
// 监听 并创建 新的渲染评论列表 数据watch(()=>originCommentListData.data,
updateCommentData,{deep:true,immediate:true})
- updateCommentData 这时数据被侦听到变化时,执行的函数- 下一点阐述
{deep:true,immediate:true}
执行深度侦听与立即侦听(页面初始加载就执行一次)
🦊(一二级评论更新-新增后)的注意❗❗-(重点)
- 一级评论新增直接push进源数据
- 一级评论新增同样直接push进源数据
- watch 监听 会 实时更新整合数据
- 注意❗❗-此时问题出现,一级评论直接渲染,但是二级评论展开由
isShowChild
控制 - 那新增 二级评论后 watch 整合对象实时更新的 isShowChild 会变成默认的
fasle
, 此时执行 重新渲染,对应得(此前新增)二级就不会展开 - 解决方式:
- 将新增得二级评论所在得整合对象中的 itemid 在外面使用 响应式数据 存起来(
levelTwoReControlId
) - 使用生命周期的更新函数
onUpdated
(更新渲染完成后)- 读取更新后新的整合对象render
根据levelTwoReControlId
找到对应得二级评论所在,改变其中的isShowChild
为true,之后清空levelTwoReControlId
的值- 这样 解决决了 二级评论 新增后 (页面更新渲染)不展开二级评论的问题
🦊通过 函数控制
isShowChild
得布尔值变化
- 绑定在
回复
上
🦊源码注意事项!
整合对象 对象要用 ref 响应式 来存储
- 因展开二级评论时,需要修改isShowChild
- 但是 要用computed监听原始数据并缓存结果 且不建议直接修改 computed 的值
不能直接修改 computed 的值
- !!!computed 得到的属性 不要去直接操作了改变其值
- 就是不能修改 computed 的值
深拷贝使用,隔绝创建的整合对象与源数据的影响
- 因为对于 整合对象(上文有解释) 涉及操作,所以要隔绝引用地址的影响
- 此处源数据 就是 数组包对象 (不复杂),使用JSON序列化(
JSON.parse(JSON.stringify(Obj))
)即可满足深拷贝的需求
时间毫秒转换
// 时间戳 转换 处理functiontimeToggle(_time){let commentDate =newDate(_time)let year = commentDate.getFullYear()let month = commentDate.getMonth()+1let date = commentDate.getDate()let commentClock = commentDate.toString().split(' ')[4]return`${year}/${month}/${date}${commentClock}`}
🐉(待改进)
- 评论 时间排序处理
- 样式优化
- 一二级评论新增函数合并
作为练手,项目还存在诸多不足待发现,后续持续改进
🦖我是Sam9029,一个前端,坚信应无所往
文章若有错误,敬请指正🙏
**🐱🐉🐱🐉恭喜你,都看到这了,求收藏,求评论,求一个大大的赞👍!不过分吧**
Sam9029的掘金主页:Sam9029的掘金主页
数合并
版权归原作者 Sam9029 所有, 如有侵权,请联系我们删除。