【Vue2】前端实现无限滚动加载

先提前预告一下:

  • 如果需要的是单个确定高度的容器组里进行无限滚动刷新,则使用InfiniteScroll最方便

  • 而如果无限滚动依赖的是整个窗口的滚轮到底部,则使用法二才行。ElemntUI的InfiniteScroll无法实现

法一:ElemntUI的InfiniteScroll

组件 | Element

纯模仿官网即可,一定要注意v-infinite-scroll只能是设置在某个独立容器中,而不能是整个页面窗口,如图:

无法对整个页面窗口实现。【所以这个容器必须设置高度,如果没有高度,则默认是一开始就直接疯狂加载响应】

在这里插入图片描述

尝试成功的代码展示:

<el-card 
        class="message-card"
        v-infinite-scroll="load"
        :infinite-scroll-disabled="this.loading || this.noMore"
        infinite-scroll-immediate='false'
        >
        <div v-for="(item, i) in this.messages">
//用到三个变量,offset是跳过第几个
//loading和noMore都是用于什么时候禁用无限滚动加载调用方法
offset: 0,
loading: false,
noMore: false,
messages: []
load(){
    //如果是第一次加载,交给mounted而不是交给scroll的加载
    //或者loading = true表示当前正在加载,不要再触发方法,滚动条此时还在底部
    if(this.loading || this.offset==0) {return}
    //如果还有数据就请求
    if(!this.noMore) {
        //现在在请求
        this.loading = true
        this.$http.get("/message/"+this.offset)
        .then((res) => {
            //把数据拼上去
           this.messages = this.messages.concat(res.data.messages)
           //如果这次请求的数据不够10条,说明后面没有数据了
           if(res.data.messages.length < 10) {
               this.noMore = true;
           }
           //下一次从offset+1开始
           this.offset += 10
           //表示加载结束,此时页面也渲染好了,滚动条也不在底部,可以放开等待下一次滚动条到底部
           this.loading = false
       })
   }
},

我遇到的几个问题的解决思路,可以试试

  • 一个是自动一次性全加载了,把load()改成load
v-infinite-scroll="loadLikeMessages()" ×
改成
v-infinite-scroll="loadLikeMessages" √
然后就成功了
  • 还有一个是异常You may have an infinite update loop in a component render function.
    解决是把this.loading = false放在请求结束后的then里,因为是异步请求,如果在外面会提前执行,那么就是不断触发this.loading = true后又 = false,死循环
load(){
    if(!this.noMore) {
        //现在在请求
        this.loading = true  //《====
        this.$http.get("/message/"+this.offset)
        .then((res) => {
            xxxxxx
           this.loading = false //《======
       })
   }
   
   //如果在这里this.loading = false,就会死循环
},

法二:直接操作window窗口的滚轮事件

理论基础(重要):

判断滚动条到底部,需要用到DOM的三个属性值,即scrollTop、clientHeight、scrollHeight。

  • scrollTop : 滚动条在Y轴上的滚动距离。

  • clientHeight : 内容可视区域的高度。

  • scrollHeight : 内容可视区域的高度加上溢出(滚动)的距离。

从这个三个属性的介绍就可以看出来,滚动条到底部的条件即为scrollTop + clientHeight == scrollHeight。

举例说明:

请添加图片描述

请添加图片描述

下面先提供三个方法,用来获取scrollTop、clientHeight、scrollHeight的信息。可直接复制使用的,写在methods里

基本原理都是比较document.body.clientHeight与document.documentElement.clientHeight

documentElement 对应的是 html 标签,因此最常用document.documentElement对象来获取这些信息

//获取当前可视范围的高度
getClientHeight() {
    var clientHeight = 0;
    if (document.body.clientHeight && document.documentElement.clientHeight) {
        clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight)
    } else {
        clientHeight = Math.max(document.body.clientHeight, document.documentElement.clientHeight)
    }
    return clientHeight
},
    
//获取文档完整的高度
getScrollHeight() {
    return Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)
},

//获取当前滚动条的位置
getScrollTop() {
    var scrollTop = 0;
    //window.pageYOffset = document.documentElement.scrollTop
    if (document.documentElement && document.documentElement.scrollTop) {
        scrollTop = document.documentElement.scrollTop
    } else if (document.body) {
        scrollTop = document.body.scrollTop
    }
    return scrollTop
}

然后我们需要一个监听器,监听滚动事件,在mounted钩子函数中就进行定义,因为我们是直接给window加装的,而不是给某个组件或者标签。因此不需要加入响应事件,但是要指定监听的回调函数,并且最重要的是最后要传入一个true的参数,否则失效。但是要注意,滚动事件的监听器需要手动销毁,否则会曝出异常。

methods: { 
    //使用上面介绍的方法
    getScrollTop(){},
    getClientHeight(){},
    this.getScrollHeight(){},
    //回调函数
    windowScroll() {
        //获取三个值
        var scrollTop = this.getScrollTop()
        var clientHeight = this.getClientHeight()
        var scrollHeight = this.getScrollHeight()
        //如果满足公式则,确实到底了
        if(scrollTop+clientHeight == scrollHeight){
            //发送异步请求请求数据,同时携带offset并自增offset
            //noMore是自定义变量,如果是最后一批数据则以后都不加载
            if(!this.noMore) {
                this.$http.get("/xxxx"+this.offset).then((res) => {
                    this.news = this.news.concat(res.data.news)
                    if(res.data.news.length < 10) {
                        this.noMore = true;
                    }
                    //记得对offset进行自增
                    this.offset += 10
                })
            }
        }
    }
}
mounted() {
    window.addEventListener('scroll', this.windowScroll,true) //监听页面滚动
},
destroyed() {
    window.removeEventListener("scroll", this.windowScroll);//销毁滚动事件
}

到此已经能实现了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容