Vue向下滚动加载更多数据-scroll-案例

vue-infinite-scroll

安装

npm install vue-infinite-scroll --save

尽管官方也推荐了几种载入方式,但“最vue”的方式肯定是在main.js中加入

import infiniteScroll from 'vue-infinite-scroll'
Vue.use(infiniteScroll)

实现范例

官方给的代码范例是假设你在根组件写代码,实际上我们肯定是在子组件里写代码,所以代码也需要略作修改,下方只列有用的代码片段:

<div v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
    <div v-for="item in data" :key="item.index">{{item.name}}</div>
</div>
  data () {
    return {
      count: 0,
      data: [],
      busy: false
    }
  }
  methods: {
    loadMore: function() {
      this.busy = true
      setTimeout(() => {
        for (var i = 0, j = 10; i < j; i++) {
          this.data.push({name: this.count++ })
        }
        console.log(this.data)
        this.busy = false
      }, 1000)
    }
  }

效果

默认会载入10行数据,只要往下滚动到页面底部,就会在1秒后再次加载10条,然后继续滚动,又会加载10条。就如下图:

选项解释

v-infinite-scroll="loadMore"表示回调函数是loadMore
infinite-scroll-disabled="busy"表示由变量busy决定是否执行loadMorefalse则执行loadMoretrue则不执行,看清楚,busy表示繁忙,繁忙的时候是不执行的。
infinite-scroll-distance="10"这里10决定了页面滚动到离页尾多少像素的时候触发回调函数,10是像素值。通常我们会在页尾做一个几十像素高的“正在加载中...”,这样的话,可以把这个div的高度设为infinite-scroll-distance的值即可。

其他选项:

infinite-scroll-immediate-check 默认值为true,该指令意思是,应该在绑定后立即检查busy的值和是否滚动到底。如果你的初始内容高度不够高、不足以填满可滚动的容器的话,你应设为true,这样会立即执行一次loadMore,会帮你填充一些初始内容。
infinite-scroll-listen-for-event 当事件在Vue实例中发出时,无限滚动将再次检查。
infinite-scroll-throttle-delay 检查busy的值的时间间隔,默认值是200,因为vue-infinite-scroll的基础原理就是,vue-infinite-scroll会循环检查busy的值,以及是否滚动到底,只有当:busy为false且滚动到底,回调函数才会执行。

实战应用

可以看到,上方的例子是在不断的修改data变量,data变量的数据不断增加,这看起来是没错的。但是,实战中,我们的新数据肯定是Ajax获取的,并不是范例中的用for循环来灌入无用的自然数,而且,并不需要setTimeout,我们希望的是页面滚动到底部就立即执行Ajax,事实上,上面代码中的setTimeout只是为了模拟一个延迟加载的效果,并不是说必须要延迟1秒才Ajax。

实战中该怎么做?

只需要将这段模拟Ajax的代码改为真正的Ajax获取数据的代码即可:

      setTimeout(() => {
        for (var i = 0, j = 10; i < j; i++) {
          this.data.push({name: this.count++ })
        }
        console.log(this.data)
        this.busy = false
      }, 1000)

另外,this.busy = false也必须作为Ajax的回调


vue-scroller

安装

npm install vue-scroller -d

在main.js里面使用

import VueScroller from 'vue-scroller'
Vue.use(VueScroller)

使用

注意:scroller的使用最好设置一个高

<scroller style="top: 100px;" :height='400' :on-refresh="refresh" :on-infinite="infinite" ref="myscroller">
     <div class="order-box" v-for="(item,index) in orderList" :key="index">
                
     </div>
 </scroller>

数据

data(){
           return{
                status:'all',
                orderList:[],
                page:0,
                all_page:1,
            }
        },

下拉刷新

refresh (done) {
                setTimeout(()=>{
                    done();
                },1500)
            },

上拉加载更多

注意:done的使用,如果在数据没有赋值到模板前就调用,就会一直触发下拉函数,所以我们要在请求成功的回调中模板赋值后调用

下拉的函数是绑定属性的方式绑定在scroller标签上的,所以我们不需要在created里面调用一次请求函数,页面初始化的时候回自动调用一次下拉的函数,从而获取到第一页的数据

//下拉触发

infinite (done) {
                if(this.page>=this.all_page){
                    setTimeout(()=>{
                        this.$refs.myscroller.finishInfinite(true);
                    },1500)
                }else{
                    
                    setTimeout(()=>{
                        this.page++;
                        this.getorderList(done)
                        
                    },500);
                }
            },

getorderList(done){
                this.$http({
                    method:'post',
                    url:'/seckill/server/orderList',
                    data:{
                        jwt:this.jwt,
                        status:this.status,
                        page:this.page,
                        page_size:5
                    }
                }).then(res=>{
                    if(res.data.code == 0){
                        
                        
                        this.orderList.push.apply(this.orderList,res.data.data.list)
                        this.$refs.myscroller.finishInfinite(true)

                        this.page = res.data.data.page
                        this.all_page = res.data.data.all_page
                        done();
                    }else{
                       
                    }
                })
            },

注意

如果涉及到tab栏切换,需要重新设置scroller的状态.finishInfinite(false)参数为false时会从新调用一次上拉函数,从而重置当前scroller的状态

 goodsAll(){
                this.status = 'all'
                this.page = 0
                this.all_page = 1
                this.$refs.myscroller.finishInfinite(false);
                this.orderList = []
            },

triggerPullToRefresh() 触发下拉刷新

finishPullToRefresh() 完成下拉刷新

this.$refs.my_scroller.finishInfinite(false)
finishInfinite(isNoMoreData :Boolean) 当参数为false时,上拉获取数据可以重新调用。当参数为true,上拉获取数据回调函数停止使用,下拉下部不再显示loading,会显示‘’暂无更多数据


vue-infinite-loading

安装

npm install vue-infinite-loading --save

组件内使用

// 组件类使用
import InfiniteLoading from 'vue-infinite-loading';

export default {
  components: { InfiniteLoading }
}

//使用 基础版
<infinite-loading
  spinner="spiral"
  @infinite="infiniteHandler"
  :distance="200"
  class="infinite-loading-wrap"
>
  <!-- <div slot="spinner">Loading...</div> -->
  <div slot="no-more">No more Data</div>
  <div slot="no-results">No results Data</div>
  <!-- <div slot="error" slot-scope="{ trigger }">
	Error Data, click <a href="javascript:;" @click="trigger">here</a> toretry
  </div> -->
</infinite-loading>

基本用法 

<template>
  <div>     
		<p v-for="(item,index) in list" :key="index">      
			<span v-text="item"></span>     
		</p>     
		<!--infinite-loading这个组件要放在列表的底部,滚动的盒子里面!-->
		<infinite-loading
			spinner="spiral"
			@infinite="infiniteHandler"
			:identifier="infiniteId"
			:distance="200"
			class="infinite-loading-wrap"
		>
			<div slot="spinner">Loading...</div>
			<div slot="no-more">No more Data</div>
			<div slot="no-results">No results Data</div>
			<div slot="error" slot-scope="{ trigger }">
			  Error Data, click <a href="javascript:;" @click="trigger">here</a> toretry
			</div>
		</infinite-loading>  
	</div>
</template>

<script>  
import InfiniteLoading from 'vue-infinite-loading';
  export default {
    data() {
      return {
		  infiniteId: +new Date(), // 重置滚动状态 改变
		  page: 1,
        list: []
      };
    },
    methods: {
		// 重置滚动状态
		rest(){
		  this.list = [];
		  this.page = 1;
		  this.infiniteId += 1;
		},
      async infiniteHandler($state) {
			// 模仿请求数据
			const res = await this.$axios.workList({ page: this.page, pagesize: 20 });
			  if (res.data.list.length) {
				this.page += 1;
				this.list = this.list.concat(res.data.list);
				$state.loaded();
			  } else {
				$state.complete();
			  }
        // 这里模仿加载延迟1秒钟
        //setTimeout(() => {
         // let temp = [];
         // for (let i = this.list.length + 1; i <= this.list.length + 20; i++) {
          //  temp.push(i);
         // }
         // this.list = this.list.concat(temp);
         // $state.loaded();
        //}, 1000);
        //},
    },
    components: { InfiniteLoading }
  }
</script>

 分页用法

<template>
  <div>
    <ul>
      <li class="hacker-news-item" v-for="(item, key) in list"></li>
    </ul>
    <infinite-loading @infinite="infiniteHandler">
      <span slot="no-more">No more Data</span>
    </infinite-loading>
  </div>
</template>    

<script>
import InfiniteLoading from "vue-infinite-loading";
import axios from "axios";
export default {
  data() {
    return {
      list: [],
    };
  },
  methods: {
    infiniteHandler($state) {
      let api = "http://xxx.com/xxx"; // api为你请求数据地址
      axios
        .get(api, {
          params: {
            // 页码参数(10条每页)
            page: this.list.length / 10 + 1,
          },
        })
        .then((response) => {
          if (response.data.length) {
            // response.data为你请求接口返回的数组列表
            this.list = this.list.concat(response.data);
            $state.loaded();
            if (this.list.length / 10 === 10) {
              // 这里是加载了10页数据,设置不在加载
              $state.complete();
            }
          } else {
            $state.complete();
          }
        });
    },
  },
  components: { InfiniteLoading },
};
</script>

说明: $state: 该组件会传递一个特殊的事件参数$state给事件处理器来改变加载状态,$state参数包括三个方法,它们是loaded方法,complete方法和reset方法。

  • loaded方法用于在每次加载数据后停止播放动画,然后该组件将准备好进行下一次触发。
  • complete方法用于完成完整的无限加载,则该组件将不再处理任何滚动操作。如果在loaded调用complete方法时永远不会调用该方法,则此组件将显示用户的结果消息,如果不是,则将显示不再有用户消息,并且可以按slot设置其它内容
  • reset方法是将组件返回到原来的状态

条件用法

<template>
    <div class="hacker-news-list">
          <div class="hacker-news-header">
            <!--下拉改变-->
            <select v-model="tag" @change="changeFilter()">
                  <option value="story">Story</option>
                  <option value="history">History</option>
            </select>
              <!--或者点击改变-->
            <button @click="changeFilter()">搜索</button>
          </div>
          <ul>
              <li class="hacker-news-item" v-for="(item, key) in list"></li>
           </ul>
           <!--不要忘记设置这个 ref="infiniteLoading"-->
          <infinite-loading @infinite="infiniteHandler" ref="infiniteLoading">
            <span slot="no-more">No more data</span>
          </infinite-loading>
    </div>
</template>

<script>
    import InfiniteLoading from 'vue-infinite-loading';
    import axios from 'axios';

    export default {
          data() {
            return {
                  list: [],
                  tag: 'story',
            };
          },
          methods: {
            infiniteHandler($state) {
                  const api="http://xxx.com/xxx";
                  // api为你请求数据地址
                  axios.get(api, {   
                    params: {
                        // 改变的条件参数
                          tags: this.tag,  
                          page: this.list.length / 10 + 1,
                    },
                  }).then(({ data }) => {
                    if (data.result.length) {
                          this.list = this.list.concat(data.result);
                          $state.loaded();
                          if (this.list.length / 20 === 10) {
                            state.complete();
                          }
                    } else {
                          $state.complete();
                    }
                  });
            },
            //改变条件条用此方法
            changeFilter() {
                  this.list = [];
                  this.$nextTick(() => {
                    this.$refs.infiniteLoading.$emit('$InfiniteLoading:reset');
                  });
            },
          },
          components: { InfiniteLoading }
    }
</script>

防抖

import { debounce } from "lodash"; // 防抖

// 防抖
get: debounce(async function () {
  let k = await this.$axios.getList_API();
  console.log(k, "防抖版");
}, 1000),

评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JackieDYH

谢谢您嘞!我会继续加油地

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值