滚动加载或者说是无限加载,是一种当今非常流行的列表显示方式。当一个列表内容太长,通常需要使用分页的形式去展现出来,可是老是需要用户去点击下一页又显得很不人道,于是滚动加载的技术就出来了,只要内容滚动到底部,就自动加载出下一页的内容出来,用户体验刚刚的。
在这个例子当中,我用了asp.net mvc,首先对数据进行分页输出JSON,再利用Vue.js配合axios,通过AJAX的方法获取数据,最后使用vue-infinite-scroll实现滚动加载。
得到分页数据,在控制器当中,新建一个Getlist,pageIndex代表当前是第几页,pageSize是一页显示多少笔数据,最后totalCount返回一个这个列表的总数据。
public List<Product> Getlist(int pageIndex, int pageSize, ref int totalCount)
{
var list=(from p in listall orderby p.ID descending select p).Skip((pageIndex - 1) * pageSize).Take(pageSize);
totalCount = listall.Count();
return list.ToList();
}
接着,我们还需要生成一个已经分页完成的JSON,并且记录好总页数,一并输出:
[HttpPost]
public ActionResult ShowthePro(int? page)
{
int pageSize = 8;
int pageIndex = page ?? 1;
int totalCount = 0;
var listpage = Getlist(pageIndex, pageSize, ref totalCount);
int totalpage = (totalCount / pageSize) + 1;
return Json(new {
count=totalpage,
data=listpage
}, JsonRequestBehavior.AllowGet);
}
这个时候,我们先使用Vue.js和axios测试一下不自动分页,看看有没有什么问题。先写js:
Vue.prototype.$http = axios;
new Vue({
el: '#Pro',
data: {
peps: ''
},
mounted() {
this.$http.post('/Json/ShowthePro?page=1').then(response=>this.peps = response.data.data);
}
})
然后将视图的模板做好:
<div class="row" id="Pro">
<article class="work-item" v-for = "pep in peps">
<a :href=pep.url class="icon fa-desktop" target="_blank"><img :src=pep.img alt="" />
<h3>{{pep.name}}</h3></a>
</article>
</div>
运行成功,接着我们就要用到vue-infinite-scroll来实现滚动加载。
vue-infinite-scroll Github 主页,可以去这里下载,然后本地加载,当然也可以使用CDN: https://unpkg.com/vue-infinite-scroll。
选项
选项 | 说明 |
---|---|
infinite-scroll-disabled | 如果此属性的值为true,则无限滚动将被禁用。 |
infinite-scroll-distance | Number(default = 0)当元素底部与窗口底部的距离达到这个数值时,执行v-infinite-scroll |
infinite-scroll-immediate-check | Boolean(default = true)指示在绑定后应立即检查该伪指令。 如果内容不够高以填满可滚动容器,则很有用。 |
infinite-scroll-listen-for-event | 当Vue实例中发生事件时,无限滚动将再次检查。 |
了解了基本应用后,我们首先加载vue-infinite-scroll到我们页面
<script src="/Scripts/vue-infinite-scroll.js"></script>
接着修改视图代码,对#Pro增加选项:
<div class="row" id="Pro" v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
.......
</div>
最后修改js代码,这是很关键的一步,我们已经完成后端分页并且以JSON输出,那么在这里我们只需要让其滚动就自动加载分页好的JSON,当页数到达总数时,我们就停止滚动加载。
从网上扒下一个实例,我们就照这个实例进行修改好了:
<template>
<div class="group-container" v-infinite-scroll="getActiveByAxios" infinite-scroll-disabled="busy" infinite-scroll-distance="10">
</div>
<load-more tip="正在加载" v-if="showLoading"></load-more>
</template>
<script>
import Vue from 'vue'
import Axios from 'axios'
import { LoadMore } from 'vux'
import infiniteScroll from 'vue-infinite-scroll'
Vue.use(infiniteScroll);
export default{
data(){
return {
showLoading:true,
busy: false,
pageInfo:{
count:0,
pageIndex:1,
pageSize:5
},
}
},
methods:{
getActiveByAxios(){
if((that.pageInfo.pageIndex - 1) * that.pageInfo.pageSize > that.pageInfo.count){
that.busy = false;
that.showLoading = false;
return;
}
Axios.get('url',{
params:{
pageSize:that.pageInfo.pageSize,
pageNum:that.pageInfo.pageIndex
}
}).then(function (response) {
if (response.data.success){
let list = response.data.data.commentList;
that.comments = that.comments.concat(list);
that.pageInfo.count = response.data.data.page.count;
that.pageInfo.pageIndex += 1;
setTimeout(() => {
that.busy = false;
}, 10);
}
}).catch(function (error) {
})
}
}
}
</script>
我第一次写的时候发生了一点意外,就是没有使用concat连接起来,导致页面一页一页的翻过去但没有累加起来:
<script>
Vue.prototype.$http = axios;
var page = 1;
new Vue({
el: '#Pro',
data: {
pros: ''
},
busy: false,
methods: {
loadMore: function () {
this.busy = true;
setTimeout(() => {
this.$http.post('/Json/ShowthePro?page=' + page).then(response=>this.pros = response.data.data);
this.busy = false;
}, 1000);
page++;
//End fro loadMore
}
}
})
</script>
可是一旦concat连接起来,JSON数据就会出现连接不上的情况,我在Chorme安装了Vue Dvetool插件后,看到连接的JSON数据发生错误,我觉得是初始化的JSON和第一页的JSON数据concat起来发生错误,那么只要让代码确认初始化的JSON不参与concat就可以了,代码相当简单:
vm.$http.get('/Json/ShowthePro?page=' + pages).then(
function (response) {
var list1 = response.data.pros;
if (vm.pros.length == 0) {
this.pros = list1;
}
else {
var list2 = vm.pros;
vm.pros = list2.concat(list1);}
pages++;
setTimeout(() => {
vm.busy = false;
}, 1000);
});
测试通过。
为了防止当前页面超过所有页面还要继续读取数据,我这里使用了一个布尔变量,当超过页面总数时,整个无限加载就停止运行。
完整代码如下:
Vue.prototype.$http = axios;
var pages = 1;
var totrue = true;
new Vue({
el: '#Pro',
data: {
pros:''
},
busy: false,
methods: {
loadMore: function () {
this.busy = true;
var vm = this;
if (totrue){
vm.$http.get('/Json/ShowthePro?page=' + pages).then(
function (response) {
var list1 = response.data.pros;
var count = response.data.count;
console.log(count);
if (vm.pros.length == 0) {
vm.pros = list1;
}
else {
if (pages <= parseInt(count)){
var list2 = vm.pros;
vm.pros = list2.concat(list1);
}
else {
totrue = false;
}
}
pages++;
setTimeout(() => {
vm.busy = false;
}, 1000);
});
} else {
}
//End fro loadMore
}
}
})
每次开始一个新的框架或者新的语言,就像初恋中的男女一样,在没有确定关系之前各种试探各种伤害,等到完全上手以后,各种温柔各种甜蜜~~
网友评论