XingYun blog
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具

XingYun

冲!
  • JS基础

    • 图解js原型链
    • JS Event Loop
    • 对象的底层数据结构
    • 让你的JavaScript代码简单又高效
    • 函数参数按值传递
    • 判断数据类型
    • 浮点数精度问题和解决办法
    • 常用方法snippet
    • 实现Promise
    • 防抖和节流
    • 巧用sort排序
  • CSS && HTML

    • CSS也需要性能优化
    • class命名规范
    • em、px、rem、vh、vw 区别
    • CSS揭秘阅读笔记
  • 浏览器

    • 浏览器是如何渲染页面的
    • 重排和重绘
    • BOM浏览器对象模型
    • DOM事件
    • 浏览器存储
  • 数据结构

    • JS实现链表
    • JS实现栈与栈应用
    • JS实现常见排序
    • 哈夫曼编码
    • MD5算法
  • vue原理浅析

    • Vue虚拟dom与Diff算法
    • 前端打包文件的缓存机制
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
  • 前端工程化

    • 浏览器是如何渲染页面的
    • 前端打包需要gzip压缩吗
    • 前端打包文件的缓存机制
    • webpack loader和plugin
  • 轮子&&组件库

    • 实现水波浪进度球
  • 文字转语音mp3文件
  • 文件上传前后端实现
  • moment.js给定时间获取自然月、周的时间轴
  • 实现文件上传功能
  • 批量下载照片
  • leaflet改变坐标原点
  • 网络

    • 有了MAC地址 为什么还需要IP地址
    • 为什么IP地址老是变
    • 我们为什么需要IPV6
    • TCP与UDP
  • 计算机组成原理

    • ASCII、Unicode、UTF-8和UTF-16
  • VSCode

    • VSCode图片预览插件 Image preview
    • rsync:linux间的高效传输工具
  • 3个提升Vue性能的写法
  • 重读Vue文档
  • moment.js给定时间获取自然月、周的时间轴
  • Vue虚拟dom与Diff算法
  • 深入响应式原理
  • Echart样例
  • 我的Vue指令库
  • 滚动到底部加载更多
    • 实现一键换肤
    • 手写Vue数据劫持
    • vue-router核心原理与手写实现
    • computed和watch
    • vue数组为什么不是响应式
    • v-for为什么不能用index做key
    • webpack loader和plugin
    • keep-alive组件原理
    • vue插槽进化
    • Vue多层嵌套组件
    • vue生命周期hook
    • vue监听dom元素的resize事件
    • 前端打包需要gzip压缩吗
    • 实现水波浪进度球
    • Vue
    XingYun
    2022-03-25
    目录

    滚动到底部加载更多

    # 触发条件

      scrollTop = 0
      loadMore() {
        const customHeight = 200
        let el = this.$refs.movie.$el // 这里 movie 为一个vue组件 所以需要.$el获取dom
        let scrollTop = el.scrollTop
        let height = el.offsetHeight
        let scrollHeight = el.scrollHeight
        console.log('scrollHeight', scrollHeight)
        console.log('height', height)
        console.log('scrollTop', scrollTop)
        if (scrollTop + customHeight + height > scrollHeight && scrollTop > this.scrollTop) {
          // 距离底部还剩200px了 请求下一段数据
          console.log('trigger', scrollTop + customHeight + height - scrollHeight)
          this.pagination.pageNum = this.pagination.pageNum + 1
          this.getList(true)
        }
        this.scrollTop = scrollTop
      }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18

    注意这个获取的是滚动部分的父盒子的 $el

    # scrollHeight

    scrollHeight 表示盒子里面 内容的高度

    其它盒子位置属性图

    当 scrollTop + height === scrollHeight 时, 就表示滚到底了

    为了提前触发, 设置了 200px 的补偿 customHeight, 也就是滚动到了离页面底部 200px 的地方 就判定为滚到底了

    还有一个问题:需要区分滚动方向, 只有向下滚动才能触发

    这里记录了一个 top 值, 每次滚动触发时,用当前的 top 值和上一次的对比, 如果减小就不触发。

    # 滚动事件监听

    import throttle  from 'lodash/throttle'
    
    mounted() {
      this.initScroll()
    }
    
    initScroll() {
      document.addEventListener('scroll', this.fetchData, true)
      // 组件销毁时取消监听
      this.$once('hook:beforeDestroy', () => {
        window.removeEventListener('scroll', this.fetchData)
      })
    }
    
    fetchData = throttle(() => { // 节流处理
      this.loadMore()
    }, 300)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

    触发后的逻辑

      pagination: any = {
        pageNum: 1,
        pageSize: 40
      }
    
      getList(addTo: boolean = false) {
        this.getMovieListLoading = true
        getMovieList({ params: { ...this.pagination } })
          .then(({ data, code, message }: any) => {
            if (code === '000000') {
              if (addTo) {
                if (!data.list || data.list.length === 0) { // 新的数据为空 表示已经到底了
                  this.$message.warning('到底了')
                } else {
                  this.list = [...this.list, ...(data.list || [])] // 在以前的数据尾部追加新的数据
                }
              } else {
                this.list = data.list || [] // 如果不是追加 那就直接赋值list
              }
            }
          })
          .finally(() => {
            this.getMovieListLoading = 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

    html 部分

    <transition-group
      name="movie-list"
      class="movie-list"
      style="width: 100%"
      ref="movie"
    >
      <div
        class="movie__item"
        :class="{ 'is-hover': hoverIndex === i }"
        v-for="(item, i) in list"
        :key="item._id"
        @click="onShowDetail(item)"
        @mouseenter="onHover(i)"
      >
        <div class="movie-card" :style="{ background: getBackgroundUrl(item) }">
          <div class="movie-poster" :style="{ '--bgUrl': getBackgroundUrl(item) }">
            <div class="action">
              <a-icon
                class="like"
                @click.stop="onLike"
                type="heart"
                style="margin-right: 12px"
              />
              <a-icon class="delete" @click.stop="onDelete(item)" type="delete" />
            </div>
          </div>
        </div>
        <div class="movie-name">{{ item.name }}</div>
      </div>
    </transition-group>
    
    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

    # 最终效果

    #vue
    上次更新: 2023/04/05, 09:41:10
    我的Vue指令库
    实现一键换肤

    ← 我的Vue指令库 实现一键换肤→

    最近更新
    01
    JavaScript-test
    07-20
    02
    二维码的原理
    07-20
    03
    利用ChatGPT优化代码
    07-20
    更多文章>
    Theme by Vdoing | Copyright © 2021-2023 XingYun | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式