• 【Vue3-小项目】 评论列表(简易)-- 思路与实现分析


    🦖我是Sam9029,一个前端

    Sam9029的掘金主页:Sam9029的掘金主页

    **🐱‍🐉🐱‍🐉恭喜你,若此文你认为写的不错,不要吝啬你的赞扬,求收藏,求评论,求一个大大的赞!👍**

    今日本想说些啥,想想无事,便不说些啥了,话不多说,直接上活

    🐉源码实现

    展示地址:Vue3小项目–评论列表 - 码上掘金 (juejin.cn)

    效果展示:

    请添加图片描述


    🐉需求

    • 一级评论创建
    • 二级评论创建并关联一级评论
    • 二级评论的可控制展开与否
    • 评论时间戳-排序- (UNfinished)

    全为本地数据操作


    🐉源数据和接下来要创建的整合对象 格式皆为 数组包对象;

      [{},{},……]
    
    • 1
    • 源数据中 一级评论与二级评论 都在对象的同一属性层级(且有对应的不同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},
      ……
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    🐉整体思路

    🦊DOM 同一控制 评论item 以及 评论item HTML+CSS样式

    • 所有的 评论item 都可以单独的作为一个 对象来考虑
    • 同理 新建评论的 输入框 也是一样

    🦊根据原始数据 - 创建 新对象数组--整合对象

    为什么创建整合对象
    • 便于渲染 评论列表
    • 介于评论 可以分为 一级 与 二级
    • 若有一个对象(整合对象) 同时包含 一二级的评论内容,即可放别统一管理相关联的一二级评论
    • 同时 用数组 来存储 所有的 对象(整合对象)
    • 同时要具备 响应式
    实现
    • 通过侦听器(深度加立即侦听) 操作筛选 整合对象(对象) 以下内容

      • 引入 nanoid 给每个整合对象 唯一id
      • 一级评论 parent (对象
        • 一级评论唯一
      • 二级评论 child (数组)
        • 可能有多个
      • 展开二级评论 控制 isShowChild(布尔值,默认值false)
        • 控制 二级评论的 回复展示
    • 整合对象json结构如下:
      [
        {
          itemId:''
          parent:{},
          chlid:[{},{}],
          isShowChild:false
        },
        ………
      ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    使用函数(updateCommentData)来 创建新的整合对象
    • 使用 update 意在更新,因为源数据可评论增加后会改变,单纯用创建来命名函数不太好
    • 同时可被监听器调用

    源码

    // 被渲染的数据 及`整合对象`
    let renderData = ref()
    
    function updateCommentData(){
      // 深拷贝 消除 影响源数据
      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({
          // 使用nanoid
          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
        })
      }
    
      // 
      renderData.value = JSON.parse(JSON.stringify(newRenderData))
    
      // 测试输出
      // console.log(JSON.parse(JSON.stringify(renderData.value))) 
    
      // 返回筛出数据 return 此场景可有可无
      return newRenderData
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    关键解析:

    • 使用一级评论的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}
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 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)))即可满足深拷贝的需求
    时间毫秒转换
    // 时间戳 转换 处理
    function timeToggle(_time){
      let commentDate = new Date(_time)
      let year = commentDate.getFullYear()
      let month = commentDate.getMonth() + 1
      let date = commentDate.getDate()
      let commentClock = commentDate.toString().split(' ')[4]
    
      return `${year}/${month}/${date} ${commentClock}`
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    🐉(待改进)

    • 评论 时间排序处理
    • 样式优化
    • 一二级评论新增函数合并

    作为练手,项目还存在诸多不足待发现,后续持续改进


    🦖我是Sam9029,一个前端,坚信应无所往

    文章若有错误,敬请指正🙏

    **🐱‍🐉🐱‍🐉恭喜你,都看到这了,求收藏,求评论,求一个大大的赞👍!不过分吧**

    Sam9029的掘金主页:Sam9029的掘金主页
    数合并

  • 相关阅读:
    第二课第一周第4-6节 医学预后案例欣赏+作业解析
    接口性能优化的11个小技巧,每个都是精髓
    JavaSE - 数组的定义、使用、内存分布、应用
    HTTP状态码
    【使用malloc函数动态模拟开辟二维数组的三种方法】
    行人属性识别二:添加新网络训练和自定义数据集训练
    零代码编程:用ChatGPT批量调整文件名称中的词汇顺序
    周赛372(正难则反、枚举+贪心、异或位运算、离线+单调栈)
    HUDI概述
    图04---最小生成树与实现
  • 原文地址:https://blog.csdn.net/m0_61486963/article/details/126903874