Vue 组件scroll,实现加载更多,防抖,刷新
(该组件利用到了iscroll)
实现思路
利用iscroll插件实现可滚动的功能,然后利用iscroll的api(myScroll.refresh())去进行刷新滚动条,得到刷新后的滚动条高度。vue里有个nextTick的方法,作用是等dom渲染完执行回调函数,利用这个作用可以在加载完数据并且渲染成功后才能进行加载请求更多的数据,优化项目。为了减少耦合度,加载更多,是否可加载,刷新全部在要使用的组件上控制。
1. 创建一个组件"my-scroll.vue",可接收三个props,分别实现刷新refresh,加载更多onload,判断是否可以加载更多的标志canLoad
<template>
<div id="myScroll" ref="myScroll">
<div class="scrollWrap">
<!-- 接收到的slot -->
<slot></slot>
</div>
</div>
</template>
<script>
// 从外面引入的iscroll-probe
import IScroll from "../lib/iscroll-probe";
export default {
name: "myScroll",
props: {
refresh: Function,
onload: Function,
canLoad: Boolean
},
data() {
return {
myScroll: null
};
},
methods: {
// 控制滚动条的刷新
fresh() {
if(this.myScroll){
this.myScroll.refresh();
}
}
},
mounted() {
// 页面挂载完成初始化iscroll
this.myScroll = new IScroll(this.$refs.myScroll, {
bounce: true,
tap: true,
mouseWheel: true,
probeType: 3,
bounce: false
});
// 滚动条滚动前刷新
this.myScroll.on("beforeScrollStart", ()=> {
this.myScroll.refresh();
});
// 监测滚动条的变化,达到条件加载更多
this.myScroll.on("scroll", () => {
if (Math.abs(this.myScroll.maxScrollY - this.myScroll.y) < 500) {
if (this.canLoad && this.onload) {
this.onload();
}
}
});
}
};
</script>
<style lang="scss" scoped>
// 该组件的样式
#myScroll {
width: 100%;
position: absolute;
left: 0;
top: 0;
bottom: 0;
overflow: hidden;
}
</style>
2. 使用方法
(1)src文件里创建一个plugin文件夹,用来管理全局插件
//引入创建的my-scroll.vue
import myScroll from './../components/my-scroll.vue'
export default {
//全局注册
install(Vue){
// 使用自定义的滚动组件
Vue.component(myScroll.name, myScroll);
}
}
在src目录下的main.js引入plugin并使用
import Vue from 'vue'
import plugin from './plugin'
import App from './App.vue'
import router from './router'
import store from './store'
//移动端适配的插件
import 'lib-flexible/flexible'
Vue.config.productionTip = false
Vue.config.devtools = true;
//use使用plugin
Vue.use(plugin);
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
(2)不全局注册,在要使用的地方直接import
3. 使用的例子(部分代码)
<template>
<myScroll :onload="loadAction" :canLoad="canload" ref="myScroll">
<!-- 美宿种草机 -->
<Grass :grassList="grassList" />
<!-- 没有更多了 -->
<p v-if="noMore" class="foot">没有更多了</p>
</myScroll>
</template>
<script>
import Grass from "./component/grass";
import { mapActions } from "vuex";
export default {
components: {
Grass
},
data() {
return {
canload: true,
//判断是否还有数据可加载的值
noMore: false,
grassList: []
};
},
methods: {
//触发加载更多的请求
loadAction() {
this.canload = false;
this.getGrass();
},
// 获取种草数据
...mapActions("home", { requestGrass: "requestGrass" }),
async getGrass() {
// 如果没有更多了就
if (this.noMore) return;
let { data } = await this.requestGrass();
// 如果是第一次请求
if (this.grassList.length === 0) {
this.grassList = data.list;
} else {
// 不是第一次请求
this.grassList = this.grassList.concat(data.list);
//如果加载的总条数大于给的值,不能加载
if (this.grassList.length >= data.count) {
this.noMore = true;
}
}
// 渲染完dom进行的操作,防抖
/************** 关键性代码,实现防抖 *****************/
this.$nextTick(() => {
//利用ref调用myscroll组件里面的方法进行刷新滚动条高度
this.$refs.myScroll.fresh();
//改变可否加载的状态
this.canload = true;
});
}
},
created() {
// 请求种草数据
this.getGrass();
}
};
</script>
vue目录结构