头条案例文章评论功能模块

文章评论

#1、业务功能分析

#2、展示文章评论列表

#2.1、准备组件

为了更好的开发和维护,这里我们把文章评论单独封装到一个组件中来处理。

创建组件 src/views/article/components/comment-list.vue

<template>
    <van-list
      v-model="loading"
      :finished="finished"
      finished-text="没有更多了"
      @load="onLoad"
    >
        <van-cell v-for="item in list" :key="item" :title="item"></van-cell>
    </van-list>
</template>
<script>
  export default {
    name: "CommentList",
    components:{},
    props: {},
    data() {
      return {
        list: [], // 评论列表
        loading: false, // 上拉加载更多的 loading
        finished: false // 是否加载结束
      };
    },

    methods: {
      onLoad() {
        // 异步更新数据
        setTimeout(() => {
          for (let i = 0; i < 10; i++) {
            this.list.push(this.list.length + 1);
          }
          // 加载状态结束
          this.loading = false;

          // 数据全部加载完成
          if (this.list.length >= 40) {
            this.finished = true;
          }
        }, 500);
      }
    }
  };
</script>

article/index.vue导入、注册、使用组件

import CommentList from './components/comment-list'

components:{
    // 其他注册...
    CommentList
}

<van-divider>正文结束</van-divider>
<!------------------------------ 文章评论列表-------------------------------------->
<comment-list/>
<!------------------------------ /文章评论列表 ------------------------------------->

#2.2、获取数据并展示

提示:有评论数据的文章 id :短文章==>1323981393964826624, 长文章==>138671

步骤:

  • 封装接口
  • 请求获取数据
  • 处理模板

实现:

1、在 api/comment.js 中添加封装请求方法

/**
 * 评论请求模块
 */
import request from '@/utils/request'

/**
 * 获取文章评论列表
 */
export const getComments = params => {
  return request({
    method: 'GET',
    url: '/v1_0/comments',
    params
  })
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

2、请求获取数据

  • 父组件article/index.vue 传入文章id

    <comment-list :source="article.art_id"/>
    

    1

  • 子组件commnent-list定义自定义属性接收

    props: {
        source: {
          type: [Number, String, Object],
          required: true
        }
     }   
    

    1
    2
    3
    4
    5
    6

  • 导入请求方法

    import { getComments } from '@/api/comment'
    

    1

  • 定义相关变量

    data(){
        return{
            //其他变量..
            offset: null, // 获取下一页数据的标记
            limit: 10,
            error: false
        }
    }
    

    1
    2
    3
    4
    5
    6
    7
    8

  • 书写处理事件函数

      methods: {
        async onLoad () {
          try {
            // 1. 请求获取数据
            const { data } = await getComments({
              type: 'a', //  评论类型,a-对文章(article)的评论,c-对评论(comment)的回复
              source: this.source.toString(), // 源id,文章id或评论id,【可能有大数字,所以执行一下toString 方法】
              offset: this.offset, // 评论数据的偏移量,值为评论id,表示从此id的数据向后取,不传表示从第一页开始读取数据
              limit: this.limit // 获取的评论数据个数,不传表示采用后端服务设定的默认每页数据量
            })
    
            // 2. 将数据添加到列表中(一定要注意是追加数据,否则列表高度不增加,形成死循环)
            const { results } = data.data
            this.list.push(...results)
    
            // 3. 将 loading 设置为 false
            this.loading = false
    
            // 4. 判断是否还有数据
            if (results.length) {
              // 有就更新获取下一页的数据页码
              this.offset = data.data.last_id
            } else {
              // 没有就将 finished 设置结束
              this.finished = true
            }
          } catch (err) {
            this.error = true
            this.loading = false
          }
        }
      }
    

    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

  • 显示评论内容

     <van-cell v-for="(item,index) in list" :key="index" :title="item.content"></van-cell>
    

    1

#2.3、展示文章评论总数量

子组件comment-list.vue触发自定义事件

  • onLoad事件函数里面 触发自定义





     




     
     // 2. 将数据添加到列表中
     const { results } = data.data
     this.list.push(...results)
    
    // 把文章评论的总数量传递到外部
    this.$emit('onload-success', data.data)  // <========== 增加这一句
    
    // 3. 将 loading 设置为 false
    this.loading = false
    

    1
    2
    3
    4
    5
    6
    7
    8
    9

  • 默认情况下只有滚动到了评论列表区域才会触发onLoad事件,所以我们需要再created里面主动触发一次,保证一开始就触发

     

     
      created () {
        this.onLoad()
      }
    

    1
    2
    3

父组件article/index.vue中监听自定事件

  • 定义变量存放总数量

     

     
    data(){
        //其他变量...
        totalCommentCount:0  // 文章评论总数量
    }
    

    1
    2
    3
    4

  • 绑定给展示组件的属性



     

     
    <van-icon
       class="comment-icon"
       name="comment-o"
       :info="totalCommentCount"
     />
    

    1
    2
    3
    4
    5

  • 监听自定义事件,赋值给变量



     



     
     <!-- 文章评论列表 -->
    <comment-list
         :source="article.art_id"
         @onload-success="totalCommentCount = $event.total_count"
    />
    <!-- /文章评论列表 -->
    

    1
    2
    3
    4
    5
    6

#2.4、文章评论项

创建 article/components/comment-item.vue

<template>
  <van-cell class="comment-item">
    <van-image
      slot="icon"
      class="avatar"
      round
      fit="cover"
      src="https://img.yzcdn.cn/vant/cat.jpeg"
    />
    <div slot="title" class="title-wrap">
      <div class="user-name">用户名称</div>
      <van-button
        class="like-btn"
        icon="good-job-o"
      >赞</van-button>
    </div>

    <div slot="label">
      <p class="comment-content">这是评论内容</p>
      <div class="bottom-info">
        <span class="comment-pubdate">4天前</span>
        <van-button
          class="reply-btn"
          round
        >回复 0</van-button>
      </div>
    </div>
  </van-cell>
</template>

<script>
export default {
  name: 'CommentItem',
  props: {
    //每行的评论信息  
    comment: {
      type: Object,
      required: true
    }
  },
  methods: {}
}
</script>

<style scoped lang="less">
.comment-item {
  .avatar {
    width: 72px;
    height: 72px;
    margin-right: 25px;
  }
  .title-wrap {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .user-name {
      color: #406599;
      font-size: 26px;
    }
  }
  .comment-content {
    font-size: 32px;
    color: #222222;
    word-break: break-all;
    text-align: justify;
  }
  .comment-pubdate {
    font-size: 19px;
    color: #222;
    margin-right: 25px;
  }
  .bottom-info {
    display: flex;
    align-items: center;
  }
  .reply-btn {
    width: 135px;
    height: 48px;
    line-height: 48px;
    font-size: 21px;
    color: #222;
  }
  .like-btn {
    height: 30px;
    padding: 0;
    border: none;
    font-size: 19px;
    line-height: 30px;
    margin-right: 7px;
    .van-icon {
      font-size: 30px;
    }   
  }
  .liked{
   	  background-color:orange;   
   }
}
</style>

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值