Vue.js 实战系列之实现视频类WebApp的项目开发——9. 视频评论列表实现

如果想看该实战系列的其他内容,请移步至 Vue.js 实战系列之实现视频类WebApp的项目开发。

项目仓库地址,欢迎 Star


实现效果

Vue.js 实战系列之实现视频类WebApp的项目开发——9. 视频评论列表实现_第1张图片


功能实现

  1. 评论列表实现

    VideoList.vue

    只展示评论列表相关代码:

    <template>
      <div class="video-list">
        <swiper ref="mySwiper" :options="swiperOptions">
        // 视频列表
        swiper>
        
        <div class="comment-wrap">
          <div class="comment-list">
            <div class="comment-top">
              <div class="number">15条评论div>
              <div class="close">
                <span class="iconfont icon-guanbi">span>
              div>
            div>
            <div class="comment-body">
              <div class="comment-box" v-for="i in 20" :key="i">
                <div class="comment-item">
                  <img class="user-pic" src="@/assets/images/author.png" alt="" />
                  <div class="item-info">
                    <div class="replay">
                      <p class="name">八戒p>
                      <p class="replay-desc">
                        程序员不加班不加班不加班不加班不加班不加班不加班不加班
                      p>
                      <p class="time">
                        03-20
                        <span class="huifu">回复span>
                      p>
                    div>
                    <div class="zan">
                      <span class="iconfont icon-aixin">
                        <p>10p>
                      span>
                    div>
                  div>
                div>
                <div class="sub-comment-item">
                  <img class="user-pic" src="@/assets/images/author.png" alt="" />
                  <div class="item-info">
                    <div class="replay">
                      <p class="name">悟空p>
                      <p class="reply-name">不加班不加班p>
                      <p class="time">
                        03-19
                        <span class="huifu">回复span>
                      p>
                    div>
                    <div class="zan">
                      <span class="iconfont icon-aixin">
                        <p>20p>
                      span>
                    div>
                  div>
                div>
                <div class="more">
                  —— 展开60条回复
                  <span class="iconfont icon-xiajiantou">span>
                div>
              div>
            div>
            
            <div class="reply-input">
              <input type="text" placeholder="留下你的精彩评论吧" />
              <div class="input-right">
                <span class="iconfont icon-aite">span>
                <span class="iconfont icon-biaoqing">span>
              div>
            div>
          div>
        div>
      div>
    template>
    
    // 这里主要进行布局设计,暂不需要 js 操作
    
    <style lang="less" scoped>
    .video-list {
            
      height: 100%;
      .comment-wrap {
            
        position: fixed;
        left: 0;
        bottom: 0;
        height: 500px;
        width: 100%;
        border-top-left-radius: 15px;
        border-top-right-radius: 15px;
        z-index: 999;
        padding: 15px;
        background-color: #F8F8FF;
        box-sizing: border-box;
        .comment-top {
            
          display: flex;
          align-items: center;
          font-weight: 600;
          font-size: 13px;
          margin-top: 10px;
          margin-bottom: 15px;
          .number {
            
            flex: 1;
            text-align: center;
          }
          .close {
            
            position: absolute;
            right: 14px;
            top: 14px;
            color: #777;
            .icon-guanbi {
            
              font-size: 26px;
            }
          }
        }
        .comment-body {
            
          max-height: 400px;
          overflow: auto;
          .comment-box {
            
            padding-bottom: 20px;
            .comment-item,.sub-comment-item{
            
              display: flex;
              margin-top: 10px;
              .user-pic {
            
                width: 33px;
                height: 33px;
                border-radius: 50%;
              }
              .item-info {
            
                margin-left: 10px;
                display: flex;
                flex: 1 auto;
                .replay {
            
                  width: 90%;
                  .name {
            
                    color: #686868;
                    font-size: 13px;
                  }
                  .replay-desc {
            
                    padding: 5px;
                    font-size: 14px;
                    line-height: 20px;
                  }
                  .time {
            
                    color: #bbbbbb;
                    .huifu {
            
                      color: #686868;
                      font-size: 13px;
                      margin-left: 15px;
                      font-weight: 600;
                    }
                  }
                }
                .zan {
            
                  color: rgb(182, 181, 181);
                  display: flex;
                  margin-top: 10px;
                  margin-left: 33px;
                  .icon-aixin {
            
                    font-size: 24px;
                    text-align: center;
                  }
                  p {
            
                    margin-top: 0;
                    font-size: 15px;
                  }
                }
              }
            }
            .more {
            
              margin-left: 45px;
              color: rgb(177, 177, 177);
            }
          }
        }
        .reply-input {
            
          width: 100%;
          height: 50px;
          border-top: 1px solid #d9d9d9;
          position: absolute;
          bottom: 0;
          left: 0;
          align-items: center;
          display: flex;
          background-color: #fff;
          padding: 0 15px;
          input {
            
            line-height: 40px;
            width: 70%;
            padding: 0 15px;
            box-sizing: border-box;
            border: none;
            background-color: #e6e6e6;
            border-radius: 20px;
          }
          .input-right {
            
            padding-right: 15px;
            flex: 1;
            display: flex;
            justify-content: space-evenly;
            .iconfont {
            
              font-size: 30px;
              color: #999999;
            }
          }
        }
      }
    }
    style>
    

    实现效果:
    Vue.js 实战系列之实现视频类WebApp的项目开发——9. 视频评论列表实现_第2张图片

  2. 评论列表的打开关闭

    1. VideoList.vue

      使用 v-if 指令来判断 showComment 则显示列表 反之则隐藏视频列表

      只展示关键代码,完整代码请至 GitHub 查看。

      <template>
      	<div class="video-list">
      		<swiper ref="mySwiper" :options="swiperOptions">
      	    	<swiper-slide v-for="(item, index) in dataList" :key="index">
      			// ... 视频列表
      	        <div class="right-bar">
      	          <RightBar @changeCom="showOrClose">RightBar>
      	        div>
      	      swiper-slide>
      	    swiper>
      	    
      	    <div class="comment-wrap" v-if="showComment">
      	       <div class="comment-list">
      	         <div class="comment-top">
      	           <div class="number">15条评论div>
      	           <div class="close" @click="showOrClose">
      	             <span class="iconfont icon-guanbi">span>
      	           div>
      	         div>
      	         <div class="comment-body">
      	         	// ... 评论内容
      	         div>
      	         <div class="reply-input">
      	         	// ... 输入评论
      	         div>
         			div>
          	div>
      	div>
      template>
      <script>
        export default {
                
          data() {
                
            return {
                
              // 显示评论列表
              showComment: false,
            };
          },
          methods: {
                
            // 弹出或关闭评论列表
            showOrClose() {
                
              this.showComment = !this.showComment;
            },
          },
        };
      script>
      
    2. RightBar.vue

      当用户点击评论图标显示评论列表,需要给 RightBar 组件的评论图标添加一个点击事件,并且需要调用父组件中的 showOrClose() 方法,这里就要用到了 Vue 的父子组件通信与事件触发 感兴趣的小伙伴可以去看一下。

      <template>
        <div class="right-bar">
          // ...
          <div class="bar-item"> /* 点赞内容 */ div>
          <div class="bar-item">
              <div class="item-icon">
                  <span class="iconfont icon-pinglun1" @click.stop="showCom($event)">span>
                  <p>285p>
              div>
          div>
          <div class="bar-item"> /* 分享内容 */ div>
          <div class="bar-item"> /* 旋转唱片 */ div>
        div>
      template>
      
      <script>
      export default {
                
        methods: {
                
      	// 评论按钮点击事件,调用父组件的方法 
          showCom(e) {
                
            e.stopPropagation();
            this.$emit('changeCom');
            console.log('评论', e);
          },
        },
      };
      script>
      

      实现效果:

      1. 评论列表未显示(关闭): Vue.js 实战系列之实现视频类WebApp的项目开发——9. 视频评论列表实现_第3张图片
      2. 评论列表显示:
        Vue.js 实战系列之实现视频类WebApp的项目开发——9. 视频评论列表实现_第4张图片
  3. 评论列表底部弹出动画

    动画效果主要通过 vue transition 来实现的,可以给任意元素包裹并且添加离开进入的动画效果。
    关于 transition 的具体使用方法,请见:官方文档

    VideoList.vue

    <template>
      <div class="video-list">
        <swiper ref="mySwiper" :options="swiperOptions">
    	// ...
        swiper>
        
        <transition name="up">
          <div class="comment-wrap" v-if="showComment">
            // 评论内容
          div>
        transition>
      div>
    template>
    
    <style lang="less" scoped>
    .video-list {
            
      /* 评论列表弹出动画 */
      .up-enter-active, .up-leave-active {
            
        transition: all .5s;
      }
      .up-enter, .up-leave-to {
            
        opacity: 1;
        transform: translateY(100%);
      }
    }
    style>
    

总结

本章节需要注意的几个点:

  • 事件冒泡的处理方式
    • .prevent 阻止父元素的事件
    • .stop 阻止事件冒泡
  • vue transition 动画实现

上一章节: 8. 视频自动播放和上滑下拉播放与暂停

下一章节: 10. 注册登录

项目整体介绍:Vue.js 项目实战之实现视频播放类WebApp的项目开发(仿抖音app)


项目仓库地址,欢迎 Star。

有任何问题欢迎评论区留言讨论。

你可能感兴趣的:(Vue,实战系列,vue,js,css,html)