PC端实现列表懒加载

  1. 安装引入lodash

    npm i --save lodash

    import _throttle from 'lodash/throttle'

  2. 给Vue组件根标签添加滚动事件,PC端是滚动实现懒加载,所以必须要有滚动事件,不过这个滚动事件不一定是在组件的根标签上,也可以是在其他元素,但是这个元素必须是列表元素的父级以上的组件。

    <div id="recomand-show" @scroll="onScroll"></div>
    
  3. 下面来看看懒加载的实现的JS方法

    //懒加载的方法
    onScroll: _throttle(function () {
          
          
      var info = document.getElementById('recomand-show');
      var scrollTop = info.scrollTop;
      var clientHeight = info.clientHeight;
      var scrollHeight = info.scrollHeight;
    
      if (scrollHeight - clientHeight < scrollTop + 0.1) {
          
          
        if(this.loading) {
          
          
          this.loading = false;
          this.addList();
        }
      }
    }),
    async addList () {
          
          
      this.pages.pageNum ++;
      
      await recommendList(this.pages).then(res => {
          
          
          this.recommandCourse = [...this.recommandCourse,...res.rows];
          this.recommandTotal = res.total;
      })
      if (this.recommandCourse.length >= this.recommandTotal) {
          
          
          this.loading = false
          return
      }
      this.loading = true
      
    },
    

    上面的代码中用到了如下几种JS属性:

    • scrollTop :scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。

      一个元素的 scrollTop 值是这个元素的内容顶部(卷起来的)到它的视口可见内容(的顶部)的距离的度量。当一个元素的内容没有产生垂直方向的滚动条,那么它的 scrollTop 值为0。

    • clientHeight :clientHeight 属性是一个只读属性,它返回该元素的像素高度,高度包含内边距(padding),不包含边框(border),外边距(margin)和滚动条,是一个整数,单位是像素 px。

    • scrollHeight:clientHeight 属性是一个只读属性,它返回该元素的像素高度,高度包含内边距(padding),不包含边框(border),外边距(margin)和滚动条,是一个整数,单位是像素 px。

    用一张图来说明他们的关系
    在这里插入图片描述

    scrollHeight - clientHeight < scrollTop + 0.1当这句代码返回true时我们可以确定在可视区域下面是没有卷进去的内容的,也就是上图深蓝色区域的下面是没有内容的,那么此时我们就要去调用接口获取新的数据。

  4. _throttle方法主要是为了防止页面抖动

  5. 完整代码如下:

    <template>
      <div class="recommand-course" id="recomand-show" @scroll="onScroll" v-loading="recommandCourseLoading">
        <div class="rec-course">
          <div class="course-list-show">
            <div class="content_header">
              <div class="title">推荐课程</div>
            </div>
            <div v-if="isRecommandShow">
              <ul class="course">
                <li class="course_item"  :class="(index+1) % 3 === 0 ? 'mar_right' : ''" v-for="(item,index) in recommandCourse" :key="index">
                  <div class="img" @click="toVideo(item.url)">
                      <img :src="item.cover" alt=""/>
                  </div>
                  <h3>{
         
         {item.name}}</h3>
                  <p>{
         
         {item.introduction}}</p>
                </li>
              </ul>
              <div class="tip" v-if="loading">加载中...</div>
              <div class="tip" v-else>没有更多了</div>
            </div>
            <div class="none-course" v-else>
              <el-empty description="暂无数据"></el-empty>
            </div>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    import { recommendList } from '@/api/course/courseController.js'
    
    import _throttle from 'lodash/throttle'
    
    export default {
      data () {
        return {
          recommandCourse:[],
          recommandTotal:0,
          loading: true,
          pages:{
            pageSize: 9,
            pageNum: 1,
          },
          recommandCourseLoading: false,
          isRecommandShow: true,
        }
      },
      created () {
        this.getRecommendList();
      },
      methods: {
        //拼接前缀
        addPre(item) {
          return `${process.env.VUE_APP_MINIO_API}/train-platform/${item}`
        },
        getRecommendList () {
          this.recommandCourseLoading = true;
          recommendList(this.pages).then(res => {
            this.recommandCourse = [...this.recommandCourse,...res.rows];
            this.recommandTotal = res.total;
            if(this.recommandCourse !== null && this.recommandCourse.length > 0) {
              this.isRecommandShow = true;
            } else {
              this.isRecommandShow = false
            }
            this.recommandCourseLoading = false
          })
        },
        //懒加载的方法
        onScroll: _throttle(function () {
          console.log('scroll');
          var info = document.getElementById('recomand-show');
          var scrollTop = info.scrollTop;
          var clientHeight = info.clientHeight;
          var scrollHeight = info.scrollHeight;
    
          if (scrollHeight - clientHeight < scrollTop + 0.1) {
            console.log('loading',this.loading);
            if(this.loading) {
              this.loading = false;
              this.addList();
              console.log(123)
            }
          }
        }),
        async addList () {
          console.log('addList');
        
          // console.log('setTimeout',this.pages.pageNum++);
          this.pages.pageNum ++
          
          await recommendList(this.pages).then(res => {
              this.recommandCourse = [...this.recommandCourse,...res.rows];
              this.recommandTotal = res.total
          })
          
          console.log('此时数组的长度',this.recommandCourse.length);
          if (this.recommandCourse.length >= this.recommandTotal) {
              this.loading = false
              return
          }
          this.loading = true
          
        },
        toVideo(url) {
          this.$router.push({
            name: 'PlayVideo',
            query: {
              url
            }
          })
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
      .recommand-course {
        width: 100%;
        height: 80vh;
        overflow-y: scroll;
        display: flex;
        justify-content: center;
        .rec-course {
          // width: 70%;
          .course-list-show {
            width: 940px;
            // margin-left: 27%;
          }
        }
      }
    .recommand-course::-webkit-scrollbar {display:none}
    .content_header {
      // display: flex;
      // align-items: center;
      position: relative;
      width: 100%;
      height: 50px;
      div {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
      }
    }
    
    .title {
        // width: 84%;
      font-size: 18px;
      font-weight: 400;
      font-family: "思源黑体";
      // margin-top: 10px;
      padding: 0px;
      text-align: left;
      // line-height: 24px;
    }
    
    .course {
          width: 100%;
          // height: 700px;
          display: flex;
          flex-wrap: wrap;
          // justify-content: space-between;
          margin-top: 30px;
          padding: 0px;
          .course_item {
              width: 300px;
              height: 100%;
              margin-right: 20px;
              margin-bottom: 25px;
              list-style: none;
              .img {
                position: relative;
                  width: 300px;
                  height: 200px;
                  cursor: pointer;
                  img{
                      width: 100%;
                      height: 100%;
                      object-fit:cover;
                  }
                  .approval{
                      width: 300px;
                      height: 200px;
                      position: absolute;
                      top: 0px;
                      left: 0px;
                      background-color: rgba($color: #000000, $alpha: 0.5);
                      display: flex;
                      justify-content: center;
                      align-items: center;
                      p {
                          font-size: 16px;
                          color: #fff;
                      }
                  }
              }          
              h3{
                font-family: '思源黑体';
                color: rgba(31, 31, 31, 1);
                font-size: 16px;
                font-weight: 500;
                line-height: 30px;
                margin:4px 0px 3px 0px;
              }
              p {
                  margin: 0px;
                  color: rgba(97, 97, 97, 1);
                  font-size: 12px;
                  font-weight: 400;
                  font-family: '思源黑体';
              }
          }
          
          .mar_right {
              margin-right: 0px;
          }
        }
    
    .tip {
      color: gainsboro;
      text-align: center;
      padding-bottom: 20px;
    }
    
    
    </style>
    

猜你喜欢

转载自blog.csdn.net/weixin_45566730/article/details/126528200