完整的Infinite scroll无限滚动指令,下拉刷新demo / loadmore【同步官方文档同步】
问题:页面刷新后/初始加载正常,第二次进入页面,无限滚动容器则显示空白?
答案:无限滚动的容器是固定的,如果上面的ui图占满了窗口,则不再执行loadmore方法。
同步官方文档:
2017.11.16 不需要下拉刷新,仅无限滚动:
XML/HTML Code复制内容到剪贴板
- <template>
- <ul v-infinite-scroll="loadMore" infinite-scroll-disabled="loading" infinite-scroll-immediate-check="false" infinite-scroll-distance="10">
- <!-- 开始循环数据列表 -->
- <div class="class-item clear" v-for="item in teachPlanLibrary">
- <input type="checkbox" class="fl checkbox" :value="item.planId" v-model="selectedPlanIds">
- <div class="fl">{{item.planName}}</div>
- <router-link :to="'/course/edit-plan/'+item.planId" tag="div" class="fr class-icon"></router-link>
- </div>
- </ul>
- </template>
这里的infinite-scroll-immediate-check在个数比较少的时候,会比较有用,默认是true,接口请求至撑满整个容器,如果个数少,肯定撑不满,所以默认不需要它撑满,设为false
JavaScript Code复制内容到剪贴板
- <script>
- import { Loadmore } from 'mint-ui' //完整引入mint ui 可以省略不写
- export default {
- name: 'procution-support',
- data() {
- return {
- searchFilter: {
- pageNo: 1,
- pageSize: 15,
- user_id: this.$store.state.common.userId
- },
- teachPlanLibrary:[],
- loading: false, // 是否可以继续触发无限滚动列表中loading是否显示
- }
- },
- mounted() {
- this.init()
- },
- methods: {
- init() {
- //初始化载入列表
- this.searchFilter.pageNo = 1;
- this.loadList(this.searchFilter);
- },
- // 加载更多
- loadMore() {
- if(this.loading) {
- return false;
- };
- this.loading = true;
- this.searchFilter.pageNo = parseInt(this.searchFilter.pageNo) + 1; //每次加载,页码+1
- this.loadList(this.searchFilter);
- },
- loadList(params) {
- // 查询数据
- this.request.post(this.$store.state.course.api.getTeachPlanList, params).then(response => {
- this.$indicator.close(); //关闭loading
- let res = response.data;
- if(res.code == 0) {
- if(!res.data) {
- return false;
- }
- let data = JSON.parse(res.data.gsonStr); // 返回的结果数组
- let total = res.data.tot; // 返回的总条数
- this.loading = false;
- this.teachPlanLibrary = this.teachPlanLibrary.concat(data);
- this.isHaveMore(total); //根据总条数与已加载条数判断是否一致来判断是否有更多数据
- } else {
- this.$toast("获取教学计划列表失败,请重试");
- }
- // success callback
- }, response => {
- // error callback
- })
- },
- isHaveMore(total) {
- // 是否还有下一页
- if(total == this.teachPlanLibrary.length) {
- this.loading = true; //不再触发无限加载
- }
- },
- }
- }
- </script>
是否还有下一页,或者条件是 total <= 也可以
根据官方文档组建 无限滚动 + 下拉刷新的完整 源码:
XML/HTML Code复制内容到剪贴板
- <!--
- mt-loadmore 下拉刷新(额外组件)
- :bottom-method="loadBottom" 上拉刷新 这个方法注释了
- allLoaded: 是否可以上拉属性,false可以,true为禁止
- top-distance 触发 topMethod 的下拉距离
- max-distance 手指下拉的最大距离
- -->
- <mt-loadmore :top-method="loadTop" :bottom-all-loaded="allLoaded" ref="loadmore" @top-status-change="handleTopChange" :top-distance="topDistance" :max-distance="100">
- <!--
- 自定义下拉刷新html模板(可删) 标签设置 slot 属性为 top,类名为 mint-loadmore-top
- pull:组件已经被按下,但按下的距离未达到 topDistance,此时释放不会触发 top-method,列表会回到初始位置
- drop:按下的距离不小于 topDistance,此时释放会触发 top-method
- loading:组件已被释放,top-method 正在执行 每当组件的状态发生变化时,loadmore 都会触发 top-status-change 所绑定的方法名称,如handleTopChange
- -->
- <div slot="top" class="mint-loadmore-top">
- <span v-show="topStatus === 'pull'" :class="{ 'rotate': topStatus === 'drop' }">↓</span>
- <span v-show="topStatus === 'loading'">Loading...</span>
- <span v-show="topStatus === 'drop'"><i class="icon iconfont"></i> 刷新成功</span>
- </div>
- <!-- 单词列表 -->
- <ul v-infinite-scroll="loadMore" infinite-scroll-disabled="loading" infinite-scroll-distance="10">
- <li v-for="item in pageList" class="page-infinite-listitem">
- <label class="mint-checklist-label">
- <div class="text" @click="playMp3(item.data.attachment_en)">
- <span class="title">{{item.title}}</span>
- <br>
- <div class="show-word show-play">
- <span class="play"><i class="icon iconfont"></i></span>
- <span class="ptitle">{{item.data.word}}</span>
- </div>
- </div>
- <img @click="playMp3(item.data.attachment_zh)" v-lazy="item.cover" class="pic">
- <!--<router-link :to="'/detail/' + item.id"><img v-lazy="item.cover" class="pic"></router-link>-->
- </label>
- </li>
- </ul>
- <div class="text-center">
- <mt-spinner type="fading-circle" v-if="loading" v-show="!loading" class="page-infinite-loading"></mt-spinner>
- </div>
- </mt-loadmore>
- <script>
- export default {
- data: function() {
- return {
- cid: this.$route.params.cid,
- searchCondition: { //分页属性
- cid: this.$route.params.cid,
- pageNo: 0,
- pageSize: 15
- },
- pageList: [],
- allLoaded: false, // 是否可以上拉属性,false可以上拉,true为禁止上拉,就是不让往上划加载数据了
- scrollMode: "auto", // 移动端弹性滚动效果,touch为弹性滚动,auto是非弹性滚动
- loading: false, // 无限滚动列表中loading是否显示
- topStatus: "", // 下拉刷新顶部状态
- topDistance:70, // 默认就是距离70
- }
- },
- mounted() {
- this.init(); //初次访问重新设置标题名
- },
- methods: {
- init() {
- this.$store.commit('common/changePageTitle', "单词学习");
- },
- //加载列表,写入全局状态,ifRefresh是否为刷新
- loadList(searchCondition, ifRefresh) {
- // 如果是刷新就从第一页开始重新请求并加载列表
- if(ifRefresh) {
- this.$http.get(this.$store.state.common.api.getListData, {
- params: searchCondition
- }).then((response) => {
- let result = response.data;
- let param = {
- cid: this.cid,
- pageNo: searchCondition.pageNo,
- data: result
- };
- this.$store.commit("list/savePageData", param);
- this.loading = false;
- this.pageList = result.items;
- this.isHaveMore(result._links.next);
- });
- } else {
- // 如果有缓存数据
- if(this.$store.state.list.pageListSaveByCid[this.cid] && this.$store.state.list.pageListSaveByCid[this.cid][searchCondition.pageNo]) {
- // console.log(this.$store.state.list.pageListSaveByCid[this.cid][searchCondition.pageNo]);
- let result = this.$store.state.list.pageListSaveByCid[this.cid][searchCondition.pageNo];
- this.loading = false;
- thisthis.pageList = this.pageList.concat(result.items);
- this.isHaveMore(result._links.next);
- } else {
- this.$http.get(this.$store.state.common.api.getListData, {
- params: searchCondition
- }).then((response) => {
- let result = response.data;
- let param = {
- cid: this.cid,
- pageNo: searchCondition.pageNo,
- data: result
- };
- this.$store.commit("list/savePageData", param);
- this.loading = false;
- thisthis.pageList = this.pageList.concat(result.items);
- this.isHaveMore(result._links.next);
- });
- }
- }
- },
- // 加载更多
- loadMore() {
- // if(this.loading) {
- // return false;
- // };
- console.log(11);
- this.loading = true;
- this.searchCondition.pageNo = parseInt(this.searchCondition.pageNo) + 1;
- this.loadList(this.searchCondition);
- },
- isHaveMore(isHaveMore) {
- // 是否还有下一页,如果没有就禁止上拉刷新
- this.allLoaded = true; //true是禁止上拉加载
- if(isHaveMore) {
- this.allLoaded = false;
- } else {
- this.loading = true; //不再触发无限加载
- }
- },
- //下拉刷新,组件提供的下拉触发方法
- loadTop() {
- this.searchCondition.pageNo = 1;
- this.loadList(this.searchCondition, true);
- this.$refs.loadmore.onTopLoaded(); // 固定方法,查询完要调用一次,用于重新定位
- },
- handleTopChange(status) {
- this.topStatus = status;
- },
- }
- }
- </script>
- </script>
vuex的list module:
JavaScript Code复制内容到剪贴板
- import Vue from 'vue'
- import axios from 'axios'
- import { Toast } from 'mint-ui'
- import { Indicator } from "mint-ui"
- // 首先声明一个状态 state
- const state = {
- pageListSaveByCid:[],// 按照cid的列表缓存列表数据
- }
- // 更新状态
- const mutations = {
- savePageData(state,params){
- let cid = params.cid,
- pageNo = params.pageNo,
- data = params.data;
- state.pageListSaveByCid[cid] = state.pageListSaveByCid[cid]?state.pageListSaveByCid[cid]:[];
- state.pageListSaveByCid[cid][pageNo] = data;
- }
- }
- // 然后给 actions 注册一个事件处理函数,当这个函数被触发时,将状态提交到 mutaions中处理
- const actions = {
- }
- // 获取状态信息
- const getter = {
- showState(state) {
- console.log(state.msg)
- }
- }
- export default {
- namespaced: true,
- state,
- mutations,
- actions,
- getter,
- }
网上copy的,使用后也是正常的:
XML/HTML Code复制内容到剪贴板
- <template>
- <div class="List" :style="{'-webkit-overflow-scrolling': scrollMode}">
- <h1>{{ msg }} </h1>
- <p>接收路由参数:{{ $route.params.cid }}</p>
- <v-loadmore :top-method="loadTop" :bottom-all-loaded="allLoaded" :auto-fill="false" ref="loadmore" @top-status-change="handleTopChange" :top-distance=50 class="page-infinite-wrapper">
- <!--
- 自定义下拉刷新html模板 标签设置 slot 属性为 top,类名为 mint-loadmore-top
- pull:组件已经被按下,但按下的距离未达到 topDistance,此时释放不会触发 top-method,列表会回到初始位置
- drop:按下的距离不小于 topDistance,此时释放会触发 top-method
- loading:组件已被释放,top-method 正在执行 每当组件的状态发生变化时,loadmore 都会触发 top-status-change 所绑定的方法名称,如handleTopChange
- -->
- <div slot="top" class="mint-loadmore-top">
- <span v-show="topStatus === 'pull'" :class="{ 'rotate': topStatus === 'drop' }">↓</span>
- <span v-show="topStatus === 'loading'">Loading...</span>
- <span v-show="topStatus === 'drop'"><i class="icon iconfont"></i> 刷新成功</span>
- </div>
- <ul v-infinite-scroll="more" infinite-scroll-disabled="loading" infinite-scroll-distance="10" class="page-infinite-list">
- <li v-for="item in pageList" class="page-infinite-listitem">{{ item.title }}</li>
- </ul>
- <div class="text-center"><mt-spinner type="fading-circle" v-if="showLoading" class="page-infinite-loading"></mt-spinner></div>
- </v-loadmore>
- </div>
- </template>
- <script>
- import {Loadmore} from 'mint-ui';
- import {Indicator} from 'mint-ui'
- export default {
- data:function() {
- return {
- msg: '单词学习',
- searchCondition:{ //分页属性
- cid: this.$route.params.cid,
- pageNo:"1",
- pageSize:"8"
- },
- pageList:[],
- allLoaded: false, //是否可以上拉属性,false可以上拉,true为禁止上拉,就是不让往上划加载数据了
- scrollMode:"auto", //移动端弹性滚动效果,touch为弹性滚动,auto是非弹性滚动
- topStatus: '',
- showLoading:false
- }
- },
- components: {
- 'v-loadmore':Loadmore // 为组件起别名,vue转换template标签时不会区分大小写,例如:loadMore这种标签转换完就会变成loadmore,容易出现一些匹配问题
- // 推荐应用组件时用a-b形式起名
- },
- mounted(){
- this.init(); //初次访问重新设置标题名
- this.loadPageList(); //初次访问查询列表
- },
- methods: {
- init () {
- this.$store.commit('changePageTitle', '学习列表');
- },
- loadTop() { //组件提供的下拉触发方法
- //下拉刷新
- this.loadPageList();
- this.$refs.loadmore.onTopLoaded();// 固定方法,查询完要调用一次,用于重新定位
- },
- loadPageList (){
- this.searchCondition.pageNo = 1;
- this.loading = false;
- // 查询数据
- this.$http.get('http://demo996.liqinwl.com/api/v1/article/index', {
- params: this.searchCondition
- }).then((response) => {
- // 是否还有下一页,加个方法判断,没有下一页要禁止上拉
- this.isHaveMore(response.data._links.next);
- this.pageList = response.data.items;
- this.$nextTick(function () {
- // 原意是DOM更新循环结束时调用延迟回调函数,大意就是DOM元素在因为某些原因要进行修改就在这里写,要在修改某些数据后才能写,
- // 这里之所以加是因为有个坑,iphone在使用-webkit-overflow-scrolling属性,就是移动端弹性滚动效果时会屏蔽loadmore的上拉加载效果,
- // 花了好久才解决这个问题,就是用这个函数,意思就是先设置属性为auto,正常滑动,加载完数据后改成弹性滑动,安卓没有这个问题,移动端弹性滑动体验会更好
- this.scrollMode = "touch";
- });
- });
- },
- more (){
- // console.log("是否继续加载:" + this.loading);
- if(this.loading){
- return false;
- };
- this.showLoading = true; /* 在底部会有loading的图标则去掉弹出loading层 */
- // 分页查询
- this.searchCondition.pageNo = parseInt(this.searchCondition.pageNo) + 1;
- this.$http.get('http://demo996.liqinwl.com/api/v1/article/index', {
- params: this.searchCondition
- }).then((response) => {
- /* 多加一层判断,如果手速下拉的比较快,上面的中断会失效 */
- if(this.loading){
- this.showLoading = false;
- return false;
- };
- thisthis.pageList = this.pageList.concat(response.data.items);
- this.isHaveMore(response.data._links.next);
- });
- },
- isHaveMore(isHaveMore){
- // 是否还有下一页,如果没有就禁止上拉刷新
- this.allLoaded = true; //true是禁止上拉加载
- if(isHaveMore){
- this.allLoaded = false;
- }else{
- this.loading = true; //不再触发无限加载
- this.showLoading = false;
- }
- },
- handleTopChange(status) {
- this.topStatus = status;
- },
- }
- }
- </script>