Skip to content

添加之后,不停地调用加载方法 #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
skyetang opened this issue Jun 7, 2016 · 42 comments
Open

添加之后,不停地调用加载方法 #18

skyetang opened this issue Jun 7, 2016 · 42 comments

Comments

@skyetang
Copy link

skyetang commented Jun 7, 2016

一直不停地调用加载方法。根本停不下来。。。

              this.busy = true;
             var _ = this;
          $.get('getCollectList',vd,function(res){
            if(res.falg == 'success'){
                _.content = res.data.content;
                _.busy = false;
            }

感觉你们做的效果,体验都挺不错,可是我用却老是出问题,忧伤啊

@furybean
Copy link
Contributor

furybean commented Jun 7, 2016

能否提供一个可重现这个问题的用例?

@skyetang
Copy link
Author

skyetang commented Jun 7, 2016

我把主要代码贴出来,可以吗?
入口js
import Vue from 'vue'; import mystore from './myStoreIndex'; import infinit from 'vue-infinite-scroll'; Vue.use(infinit) new Vue(mystore);

methods
methods: { loadMore: function() { this.busy = true; var _ = this; var vd = {}; $.get('getCollectList',vd,function(res){ _ .content = res.data.content; _.busy = false; }) }

template
`






{{data.title}}



{{data.createTime}}

<div class="action" @click="setting">




`

就这样,每次请求了之后,就会继续重复请求。只要把busy改为false了之后,就会又执行loadMore方法。

@skyetang
Copy link
Author

skyetang commented Jun 7, 2016

已经解决了。
是因为我把_.busy =false,写到ajax里面去了,我调到外面来就好了。
但是我还是不明白,为什么放在ajax里面,会形成死循环,不停地刷。

@furybean
Copy link
Contributor

furybean commented Jun 8, 2016

busy 是应该在 ajax 结束的时候才重置为 false 的。
能把解决问题的代码贴一下么?

@skyetang
Copy link
Author

skyetang commented Jun 8, 2016

`methods: {

loadMore: function() {

this.busy = true;

var _ = this;

var vd = {};

$.get('getCollectList',vd,function(res){
_ .content = res.data.content;
_.busy = false;
})
}`

1、上面的写法,会不停地刷。。
2、关于然后昨晚上说,把busy重置为false,写在ajax外面的时候,只要屏幕动一下,就会直接加载。不管是否到了页面底部。

@hubinjie
Copy link

如果是屏幕动一下就加载,发现即便不在这个页面,在其他页面也会加载,不停的加载。。。

@furybean
Copy link
Contributor

@hubinjie 是否使用了 keep alive 的功能?

@hubinjie
Copy link

hubinjie commented Jul 19, 2016

@furybean 是的是的,咋破?
我昨天判断了一下$route.name 加了一个return

@furybean
Copy link
Contributor

@hubinjie 可以考虑控制一下 disabled 属性?

@hubinjie
Copy link

@furybean 感觉还是有问题,当你再次进来的时候又加载了,离开又停,再次进来又加载,切进来很卡

@furybean
Copy link
Contributor

如果把这个 directive 写在你要 keep alive 的组件本身呢,这样感觉就只绑定一次?

@weaponready
Copy link

@hubinjie 使用keep-alive出现了和一样的问题呢

@dingyiming
Copy link

好像跟keep-alive一起使用的确有问题,造成不同的路由页面的滚动条一动都会触发无限加载。。。而且好像不能保存滚动状态

@iversong
Copy link

不使用keep-alive切换组件后也是触发无限加载!!

@furybean
Copy link
Contributor

@iversong 这种情况能提供一个 demo 么?

@iversong
Copy link

iversong commented Aug 11, 2016

@furybean 我是在动态组件中使用,只是把你们官方例子中的loadMore方法里模拟的异步获取数据替换成ajax请求数据,问题就出现了,明天我贴个demo!

@iversong
Copy link

@furybean 我大概找到原因了,当所有数据加载完API返回空的时候,list数组的长度就不会变动触发dom更新,从而重复请求,插件内部是根据高度变化来判断吗,所有数据请求完应该怎么处理,麻烦指教!

    /**
     * 从api获取数据
     */
    loadData() {
      this.loading = true
      this.$http.get('/ajax/user/get_follow',{page: this.pageindex,pagesize:20}).then((response) => {
          if (response.ok) {
            this.onLoadData(response.data)
          }
        }, (response) => {
            // error callback
        });
    },
    /**
     * 接收API获取的数据,并追加到当前列表
     */
    onLoadData(data) {
      this.pageindex++
      let i=0, length=data.length, userItem
      if (length > 0) {
        for(; i<length; i++) {
          userItem = data[i]
          this.list.push(userItem)
        }
      } else {
        this.allLoaded = true
      }
      this.loading = false
    }

@furybean
Copy link
Contributor

@iversong 这种情况可以设置 infinite-scroll-immediate-check 为 false。

@jinjuduan
Copy link

jinjuduan commented Oct 13, 2016

infinite-scroll-immediate-check 为 false也不行,本来是往下滚动10个像素再加载的,而现在是鼠标只要往上或者往下滚动都加载;感觉这个组件处理ajax异步回调是有bug的

@jinjuduan
Copy link

jinjuduan commented Oct 13, 2016

回归本源,实现滚动加载其实没那么复杂,自己写的一个小例,亲测还行,望大家指正:

new Vue({
    el: "#vue-app",
    data: function () {
        return {
            busy: false,
        };
    },
    methods: {
        loadMore: function () {
            var _self = this;

            // 或ajax请求
            setTimeout(function () {
                console.log("has loaded");

                _self.busy = false;
            }, 1500)
        }
    },
    ready: function () {
        var _self = this;

        window.addEventListener("scroll", function (e) {
            if (window.scrollY >= document.body.scrollHeight - document.body.clientHeight - 20) {
                if (!_self.busy) {
                    _self.busy = true;

                    _self.loadMore();
                }
            }
        });
    }
});

@xiaoyi-wang
Copy link

确实,不停地调用加载方法 +1 ,按demo走的。跟楼上说的问题一致。

@andylei18
Copy link

我也遇到 此问题 没人解决吗?

@wengcd
Copy link

wengcd commented Dec 22, 2016

之前使用 vue1.0 配合 vue-infinite-scroll没问题,现在使用vue2.0好像disabled=true也会无限调用方法。

@lo6041
Copy link

lo6041 commented Mar 6, 2017

我也遇到了,请问各位大神是怎么解决的?

@wengcd
Copy link

wengcd commented Mar 8, 2017

@lo6041 调用的方法不能有括号

<component v-infinite-scroll="loadMore"></component>
<component v-infinite-scroll="loadMore()"></component>

估计是个bug

@leohgbs
Copy link

leohgbs commented Apr 10, 2017

猜测应该是scroll event触发太快了,
外面套一层debounce,效果要好很多

loadMore: debounce(function(e) {
   do ajax
},500)
export function debounce(func, wait, immediate) {
    var timeout, args, context, timestamp, result;

    var later = function() {
        // 据上一次触发时间间隔
        var last = Date.now() - timestamp;

        // 上次被包装函数被调用时间间隔last小于设定时间间隔wait
        if (last < wait && last > 0) {
            timeout = setTimeout(later, wait - last);
        } else {
            timeout = null;
            // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
            if (!immediate) {
                result = func.apply(context, args);
                if (!timeout) context = args = null;
            }
        }
    };

    return function() {
        context = this;
        args = arguments;
        timestamp = Date.now();
        var callNow = immediate && !timeout;
        // 如果延时不存在,重新设定延时
        if (!timeout) timeout = setTimeout(later, wait);
        if (callNow) {
            result = func.apply(context, args);
            context = args = null;
        }

        return result;
    };
}

@zhangwei900808
Copy link

我也遇到这个问题,我把setTimeout时间设置大点就好了,就是图片还没有完全加载完就触发了加载事件的原因,分享一下

tianjianchn added a commit to tianjianchn/vue-infinite-scroll that referenced this issue Oct 10, 2017
修复以下情况下会导致无限调用 loadMore 的情况:
1. 当调用 loadMore,产生新的高度变化,但是这个高度不够 infinite-scroll-distance 时,导致再次调用 loadMore
2. 当调用 loadMore 时,由于底部有加载动作条渲染,而实际上又没有新的数据(比如接口返回零行),导致无限调用 loadMore

ElemeFE#35
ElemeFE#18
@xuiwife
Copy link

xuiwife commented Nov 26, 2018

我也遇到这个坑爹的问题了
往下拖动后就不断的发请求
image

@Satuary
Copy link

Satuary commented Dec 19, 2018

可以试试使用infinite-scroll-immediate-check="busy"禁掉自动检查,触发loadMore的时候在开启检查

@melunar
Copy link

melunar commented Apr 9, 2019

我也遇到了 大概就是@wengcd说的

@liov
Copy link

liov commented Apr 23, 2019

:infinite-scroll-disabled="true" 无限循环怎么破

@zjlssc
Copy link

zjlssc commented Apr 28, 2019

@lo6041 调用的方法不能有括号

<component v-infinite-scroll="loadMore"></component>
<component v-infinite-scroll="loadMore()"></component>

估计是个bug

这个解决方案有效

@Meloneat
Copy link

写无限循环的代码时 同样遇到无限加载 load的情况。
后来尝试不同方式后,发现根节在于
我使用v-infinite-scroll时 未指定应用该指令的div实际高度。
当我尝试限定高度时(height:xxx; overflow-y:auto),一切都正常了,load将在拉取底部时才会被执行。
image

然而,在某些应用场景,比如 可操作的 实际滚动条范围 如果超出了应用v-infinite-scroll组件的范围,即作为他的父级或更高级时,应用v-infinite-scroll组件的标签如上图的div,那么就不能定高了(除非你一层一层的适应父级高度让含有v-infinite-scroll组件的标签能够固定高度,但如果滚动区域在在顶层,那就不好办了)。

在这种情况下,无限执行load的bug就出现了,你可以试着检查是否是因为应用v-infinite-scroll组件的标签未能固定高度而导致的。而这正是无限执行load的原因所在,应用v-infinite-scroll组件的标签高度已被内部的项目撑满。(意味着dom.clientHeight == dom.clientTop+dom.clientHeight 监测是否拉到底部的方法失效了,因为在高度被填满后始终是满足该条件的,因此load会一直执行, 如下图)
image

那么解决的办法呢

正如@isaacduane 提到的

使用
domcument.addEventListener来监测滚动是可以实现, 如果你的滚动条所处的标签(固定高度)已经超出了v-infinite-scroll的标签层级。

唯一要注意的是:要监测的标签就是你在应用滚动条的那个而非window

@Meloneat
Copy link

Meloneat commented Jul 5, 2019

那么解决的办法呢

正如@isaacduane 提到的

使用
domcument.addEventListener来监测滚动是可以实现, 如果你的滚动条所处的标签(固定高度)已经超出了v-infinite-scroll的标签层级。

唯一要注意的是:要监测的标签就是你在应用滚动条的那个而非window

补充
查看作者源码后发现,除了以上方法外,还可以:
直接在滚动条所处的标签内加上属性overflow-y: auto/scroll, 同样可以帮助定位实际发生scroll事件的标签。

@Emma1075
Copy link

@lo6041 调用的方法不能有括号

<component v-infinite-scroll="loadMore"></component>
<component v-infinite-scroll="loadMore()"></component>

估计是个bug

就是这个原因。我也遇到了。将尖括号去掉后就好使了~感谢老哥!

@kolinDul
Copy link

kolinDul commented May 7, 2020

几年的bug了也不改

@kolinDul
Copy link

kolinDul commented May 7, 2020

官网在线运行代码都有问题,没滚动自己一直加载

@wb94
Copy link

wb94 commented May 8, 2020

用 @isaacduane 的 方式实现了,放弃infinitescroll了

@ka3hun9
Copy link

ka3hun9 commented May 9, 2020

这插件须要给父元素设置一个固定高度,父元素必须要出现滚动条,功能才能正常使用。elementUI的官方案例很清楚,因为案例页面上也是有两个滚动条的,浏览器本身的滚动条,插件的父元素的滚动条。两个滚动条,呵呵 #18 (comment) @isaacduane 此方法实用。Vue 1.0的ready需要改成mounted

@skingford
Copy link

这个问题其实是官方的demo使用infinite-scroll-disabled="busy",busy为常量字符串,因此busy一直会为true,正确方法应该是 :infinite-scroll-disabled="busy",将busy当作一个变量

@954L
Copy link

954L commented Nov 17, 2020

@lo6041 调用的方法不能有括号

<component v-infinite-scroll="loadMore"></component>
<component v-infinite-scroll="loadMore()"></component>

估计是个bug

正解!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests