滚动下滑请求和vue循环v-for延迟展示dom逻辑

751#699cf94e

CON

为了方便,案列都使用vue做演示

滚动加载

逻辑:计算数据滚动区高度,计算当前滚动条离顶部高度,计算数据可视区域高度,滚动区域=离顶部高度+可视高度即到底部了。

注意:如果不提供手动加载按钮,就需要根据数据调整第一页数据填充数据区域高度使它出现滚动条。

代码示例

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div id="v">
      <div v-for="(item,i) of list" :key="i">
        <h5>{{item.id}}</h5>
        <h3>{{item.date}}</h3>
      </div>
    </div>

    <script src="https://cdn.bootcss.com/vue/2.6.8/vue.min.js"></script>
    <script>
      new Vue({
        el: '#v',
        data: {
          list: [] // 存放数据
        },
        mounted() {
          // 获取首页数据
          this.getList()

          // 绑定滚动事件
          window.addEventListener('scroll', () => this.initList())
        },
        methods: {
          getList() {
            // 模拟数据
            for (let i = 0; i < 20; i++) {
              this.list.push({
                id: Math.random(),
                date: new Date()
              })
            }
          },
          initList() {
            // 滚动条移动长度
            let sTop =
              pageYOffset ||
              document.documentElement.scrollTop ||
              document.body.scrollTop
            // 当前页面总长度
            let sHeight =
              document.documentElement.scrollHeight ||
              document.body.scrollHeight
            // 可见的页面长度
            let ch = document.documentElement.clientHeight

            // 滑到了最下面接近30px附近,获取下一页数据,防止计算不精确
            if (sTop + ch + 30 >= sHeight) {
              this.getList()
            }
          }
        }
      })
    </script>
  </body>
</html>

延迟展示

vue循环不好控制中间过程,差不多的意思也就是控制不了循环的生命周期。

逻辑:多数时候是要使用动画展示,这里分享我使用简单粗暴的逻辑,先都vue将dom渲染完毕,但全部给隐藏。

注意:display和visibility是有区别的,display在页面上不会为dom占据自己那份空间,而visibility则会,所以在结合滚动加载的时候,需要使用visibility,这里显示无所谓。

代码示例

这里使用一下动画库animate.css

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <link
      href="https://cdn.bootcss.com/animate.css/3.7.0/animate.min.css"
      rel="stylesheet"
    />
    <style>
      .no-ani {
        visibility: hidden;
      }
    </style>
  </head>
  <body>
    <div id="v">
      <div
        class="no-ani animated"
        ani="zoomIn"
        v-for="(item,i) of list"
        :key="i"
      >
        <h5>{{item.id}}</h5>
        <h3>{{item.date}}</h3>
      </div>
    </div>

    <script src="https://cdn.bootcss.com/vue/2.6.8/vue.min.js"></script>
    <script>
      new Vue({
        el: '#v',
        data: {
          list: [] // 存放数据
        },
        mounted() {
          // 获取首页数据
          this.getList()

          // 显示一下第一页
          // 没有使用到promise,所以做一下延迟,也可以利用钩子函数保证dom挂载完成
          setTimeout(() => {
            this.initList()
          }, 500)

          // 绑定滚动事件
          window.addEventListener('scroll', () => this.initList())
        },
        methods: {
          getList() {
            // 模拟数据
            for (let i = 0; i < 20; i++) {
              this.list.push({
                id: Math.random(),
                date: new Date()
              })
            }
          },
          initList() {
            // 滚动条移动长度
            let sTop =
              pageYOffset ||
              document.documentElement.scrollTop ||
              document.body.scrollTop
            // 当前页面总长度
            let sHeight =
              document.documentElement.scrollHeight ||
              document.body.scrollHeight
            // 可见的页面长度
            let ch = document.documentElement.clientHeight

            // 滑到了最下面接近30px附近,获取下一页数据,防止计算不精确
            if (sTop + ch + 30 >= sHeight) {
              this.getList()
            }

            // 未显示的列表
            let domList = document.getElementsByClassName('no-ani')

            // 扁你一下隐藏的dom
            Array.prototype.slice.apply(domList).forEach((item, i) => {
              // 判断该是否组件是否到可视页面
              if (sTop + ch > item.offsetTop) {
                // 每一个小模块都在上一个模块的基础上多200毫秒显示
                setTimeout(() => {
                  // 删除不显示控制
                  item.classList.remove('no-ani')
                  // 添加指定动画
                  item.classList.add(item.getAttribute('ani'))
                  // 删除指定属性
                  item.removeAttribute('ani')
                }, 200 * i)
              }
            })
          }
        }
      })
    </script>
  </body>
</html>

以上代码都可以直接拷贝运行

参与本文讨论

请先登录 GitHub 后留言

0/500

本文留言

0

这篇文章还没有留言,来写第一条吧。

1 / 1