一、v-infinite-scroll无限滚动组件使用详解
1、v-infinite-scroll="load" //load无限滚动加载的方法
2、infinite-scroll-disabled //是否禁用无限滚动加载
3、infinite-scroll-delay //节流时延,单位为ms
4、infinite-scroll-distance //触发加载的距离阈值,单位为px
5、infinite-scroll-immediate //是否立即执行加载方法,以防初始状态下内容无法撑满容器。
//默认情况下,infinite-scroll-disabled是false,因此如果组件使用无限滚动加载组件,即使在vue不进行加载方法的调用,组件也会调用该方法,因此如果需要控制的话,尽量是使用infinite-scroll-disabled属性来进行加载方法是否调用的控制。
二、组件无限加载原因及解决方式
1、问题:使用无限加载的div没有设置高度导致无限加载
解决方案:
<div v-infinite-scroll="load" :infinite-scroll-disabled="isInfiniteScrollDisabled" style="margin-bottom: 20px;height:640px;overflow-y:auto" //style的设置非常关键,一定要设置height高度 >
在指令使用的div一定要限定高度(height:xxx; overflow-y:auto)load加载方法将在拉取底部时才会被执行。
2、问题:为什么在vue中并没有在任何生命周期中进行load方法的调用,直接就加载了方法?
解决方案:使用 :infinite-scroll-disabled="isInfiniteScrollDisabled“属性来进行控制。
3、代码demo演示
<template>
<div class="vue-class-name">
<div
v-infinite-scroll="load"
:infinite-scroll-disabled="isInfiniteScrollDisabled"
style="margin-bottom: 20px;height:640px;overflow-y:auto"
>
<div
v-for="item in dataList"
:key="item.index"
style="display: inline-block;margin:0px 10px 10px 0px"
>
<span>{{item}}</span>
</div>
<el-empty
description="No Data"
v-if="dataList.length == 0"
style="height:650px;overflow-y:auto;text-align:center"
></el-empty>
<!-- 这个div一定要放在使用指令的div里面-->
<div align="center" v-if="dataList.length > 0">
<div class="drawer-footer">
<span v-if="pullStatus === $enum.STATUS.START">
Pull up to load more
</span>
<span v-if="pullStatus === $enum.STATUS.LOADING">
loading
<i class="el-icon-loading"></i>
</span>
<span v-if="pullStatus === $enum.STATUS.NODATA">
no more data
</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'VueName',
mixins: [],
components: {},
props: {},
data: function() {
return {
pullStatus: this.$enum.STATUS.START,
pageIndex: 1,
pageSize: 20,
dataList: [],
isInfiniteScrollDisabled: false,
};
},
computed: {},
watch: {
//事件监听:当刷新浏览器页面或者切换项目的时候进行方法调用
projectSpaceId: function(value, oldValue) {
this.dataList = [];
this.pageIndex = 1;
this.pullStatus = this.$enum.STATUS.START;
this.getLoadMoreData();
},
},
created() {},
mounted() {
//一进入页面进行方法调用
this.getLoadMoreData();
},
methods: {
getLoadMoreData() {
if (this.pullStatus != this.$enum.STATUS.START) {
return;
}
this.pullStatus = this.$enum.STATUS.LOADING;
this.isInfiniteScrollDisabled = true;
let params = {};//请求参数,可省略
this.getData(params).then(resp => {
if (data.length < this.pageSize ) {
this.pullStatus = this.$enum.STATUS.NODATA;
} else {
this.pageIndex++;
this.pullStatus = this.$enum.STATUS.START;
}
if (resp.data.length > 0) {
this.dataList = this.dataList.concat(resp.data);//数组拼接,得到拼接后的数据
}
this.isInfiniteScrollDisabled = false;
});
},
},
beforeDestroy() {
this.dataList = []; //清空数组
};
</script>
<style scoped></style>
//常量定义
export const STATUS= {
START: 0, // 上拉加载
LOADING: 1, // 加载中
NODATA: 2, // 没有更多数据
};
三、总结
当然,这个组件还有很多可以优化的地方,比如:可以将下面这一段代码抽成公共组件,使用该组件的地方,只需要传当前的pullStatus状态即可。
<div class="drawer-footer">
<span v-if="pullStatus === $enum.STATUS.START">
Pull up to load more
</span>
<span v-if="pullStatus === $enum.STATUS.LOADING">
loading
<i class="el-icon-loading"></i>
</span>
<span v-if="pullStatus === $enum.STATUS.NODATA">
no more data
</span>
</div>
同时,也可以封装成一个mixins,这样同一个项目,如果多处需要滚动分页,那么这样代码就会更加简洁和方便,下面我粘贴一下mixins里面的代码:
/**
* 页面无限滚动加载
*/
export default {
name: "infiniteScrollMixins",
data() {
return {
pullStatus: this.$enum.STATUS.START,
pageIndex: 1,
pageSize: 20,
}
},
computed: {},
created() {},
methods: {
loadMoreData() {
if (this.pullStatus != this.$enum.STATUS.START) {
return;
}
this.pullStatus = this.$enum.STATUS.LOADING;
if(this.getLoadMoreData) {
//使用该mixins的组件需要定义该方法
this.getLoadMoreData();
}
},
setPullStatus(data = []) {
if (data.length < this.pageSize ) {
this.pullStatus = this.$enum.STATUS.NODATA;
} else {
this.pageIndex++;
this.pullStatus = this.$enum.STATUS.START;
}
}
},
beforeDestroy() {},
};
如何使用封装的mixins?
1、导入: import 名称 from ‘路径’;
2、声明: mixins: [mixins名称],
3、此时mixins中定义的data/methods/computed等,在该组件中都可以直接使用,且多个使用mixins的组件的各个变量是相互独立的,值的修改在组件中不会相互影响。(此处不理解可以去学习一下mixins的相关文档)