首页 > 编程语言 > Vue向下滚动加载更多数据scroll案例详解
2022
03-01

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:;" rel="external nofollow"  rel="external nofollow"  @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:;" rel="external nofollow"  rel="external nofollow"  @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),

到此这篇关于Vue向下滚动加载更多数据-scroll-案例的文章就介绍到这了,更多相关Vue加载数据内容请搜索自学编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持自学编程网!

编程技巧