美文网首页
简单无限滚动的实现

简单无限滚动的实现

作者: frank_松 | 来源:发表于2020-03-29 21:33 被阅读0次

    在使用elementUI组件库的时候,用到了无限滚动这个功能。我没有看源码,直接在网上学习了下实现的思路,然后自己手动编码以下。在此总结下。

    假设页面上有一个盒子容器,容器内有一些子元素。容器的高度是固定的,有纵向滚动条。怎么做到滚动到底部的时候,就能触发事件查询数据呢?

    用图形的形式分析下:

    image.png

    知道思路后,我们就是想办法用代码的形式实现它即可。

    js
    子元素总高度 scrollHeight
    可视区域高度 clientHeight
    滚动条纵向偏移量 scrollTop
    

    我把代码贴上来,因为是vue技术栈,所以在vue环境开发,cdn引入即可。(还有个原因是,vue用多了之后,原生js操作dom不太会写了,尴尬 ̄□ ̄||)

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>无限滚动</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js"></script>
    </head>
    <body>
    <style>
        #div1 {
            width: 500px;
            height: 400px;
            margin: 50px auto;
            overflow-y: scroll;
        }
        .p1 {
            height: 40px;
            line-height: 40px;
            margin: 5px 0;
            background-color: #409EFF;
            color: white;
            font-size: 16px;
            text-align: center;
        }
        #div1::-webkit-scrollbar {/*滚动条整体样式*/
            width: 10px;     /*高宽分别对应横竖滚动条的尺寸*/
            height: 10px;
            scrollbar-arrow-color:rgba(0,0,0,0.2);
        }
        #div1::-webkit-scrollbar-thumb {/*滚动条里面小方块*/
            border-radius: 5px;
            -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
            background: pink;
            scrollbar-arrow-color:rgba(0,0,0,0.2);
        }
        #div1::-webkit-scrollbar-track {/*滚动条里面轨道*/
            -webkit-box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
            border-radius: 0;
            background: white;
        }
    </style>
    <div id="app">
        <div id="div1" @scroll="scrollCb">
            <p class="p1" v-for="(item, index) in list" :key="index" v-text="item"></p>
        </div>
    </div>
    
    <script>
        new Vue({
            el: '#app',
            data: {
                list: []
            },
            created() {
                for (let i = 1; i <= 10; i++) {
                    this.list.push("第"+i+"条数据");
                }
            },
            methods: {
                scrollCb() {
                    // 首先找出子元素总高度 scrollHeight
                    // 再找出可视区域高度 clientHeight
                    // 滚动条纵向偏移量 scrollTop
                    // 当 总高 - 可视区域高度 - 纵向偏移量 < 某个最小阈值 的时候,触发无限滚动
                    const dom = document.getElementById("div1");
                    const totalHeight = dom.scrollHeight;
                    const clientHeight = dom.clientHeight;
                    const scrollTop = dom.scrollTop;
                    if (totalHeight - clientHeight - scrollTop < 20) {
                        this.addList();
                    }
                },
                addList() {
                    this.list.push("无限滚动触发");
                    for (let i = 1; i <= 10; i++) {
                        this.list.push("第" + i + "条数据");
                    }
                }
            }
        })
    

    上面的样式无所谓啦,无非是想做的好看点,可能前端都这样吧。效果是这样的,每次滚动到列表底部时,就会增加列表元素。


    image.png

    进阶下:
    在vue中有自定义指令这个鬼东西,elementUI提供的无限滚动也是个自定义指令。我试着将其写成自定义指令的形式。
    样式等都是一样的,只是逻辑改了下,采用自定义指令实现

    <div id="app">
        <div id="div1" v-infinite-scroll>
            <p class="p1" v-for="(item, index) in list" :key="index" v-text="item"></p>
        </div>
    </div>
    
    <script>
        new Vue({
            el: '#app',
            data: {
                list: []
            },
            created() {
                for (let i = 1; i <= 10; i++) {
                    this.list.push("第"+i+"条数据");
                }
            },
            directives: {
              infiniteScroll: {
                  bind(el, binding, vNode) {
                      el.onscroll = () => {
                          const totalHeight = el.scrollHeight;
                          const clientHeight = el.clientHeight;
                          const scrollTop = el.scrollTop;
                          if (totalHeight - clientHeight - scrollTop < 20) {
                              vNode.context.addList(); // vNode.context指向当前vue实例
                          }
                      };
                  }
              }
            },
            methods: {
                addList() {
                    this.list.push("无限滚动触发");
                    for (let i = 1; i <= 10; i++) {
                        this.list.push("第" + i + "条数据");
                    }
                }
            }
        })
    </script>
    

    效果和第一个方法是一样的。(还有用vnode上报事件的方法,下次写)

    这样,我就简单实现了一个向下的无限滚动功能。学习一个东西的时候,最好自己尝试找解决方法。如果找不到再学习别人的,重要的是理解思路,而不是死记硬背代码,这样才能记得牢固。

    相关文章

      网友评论

          本文标题:简单无限滚动的实现

          本文链接:https://www.haomeiwen.com/subject/jafpuhtx.html