赞
踩
上一篇我们讲解了Vue的UI框架Mint UI的使用,本篇我们来通过Mint UI提供的infinite-scroll组件结合api接口实现一个上拉分页加载更多的功能。
本系列博文使用的Vue版本:2.6.11
Mint UI 中文开发文档:https://www.w3cschool.cn/mintui/
实现上拉分页加载更多的功能,需要用到Mint UI提供的infinite-scroll(无限滚动)组件。下面我们简单介绍一下该组件的使用。
infinite-scroll为Mint UI的JS组件之一,它能提供一个无限滚动的指令,即我们会初始加载一部分数据,当你拖动列表下拉时,会触发动态加载,一段简单的加载动画后,会将新加载的列表拼接在已显示的列表下,相当于我只要往下拉动列表,就会无限的加载出数据,不拉动就不加载。效果如下:
例子
为 HTML 元素添加 v-infinite-scroll 指令即可使用无限滚动。滚动该元素,当其底部与被滚动元素底部的距离小于给定的阈值(通过 infinite-scroll-distance 设置)时,绑定到 v-infinite-scroll 指令的方法就会被触发。
- <ul
- v-infinite-scroll="loadMore"
- infinite-scroll-disabled="loading"
- infinite-scroll-distance="10">
- <li v-for="item in list">{{ item }}</li>
- </ul>
这里的loadMore方法,就是为list数组再加增加10个元素:
- loadMore() {
- this.loading = true;//在加载数据的时候,暂时关闭滚动加载触发
- setTimeout(() => {
- let last = this.list[this.list.length - 1];
- for (let i = 1; i <= 10; i++) {
- this.list.push(last + i);
- }
- this.loading = false;//数据加载完毕后,再次开启滚动加载触发
- }, 2500);
- }
其中的“infinite-scroll-disabled”、“infinite-scroll-distance”的含义,见API:
这样,我们如果想实现上拉分页的效果,其实只要引入infinite-scroll组件,并且实现“v-infinite-scroll”的加载数据方法即可。
理论已经有了,下面动手来实现它吧。
我们清理一下原来的MintUI.vue页面,先引入infinite-scroll组件,写一个简单的触发方法,看看能不能触发:
- <template>
- <div id="MintUI">
- <h1>{{msg}}</h1>
- <ul
- v-infinite-scroll="loadMore"
- infinite-scroll-disabled="loading"
- infinite-scroll-distance="10">
- <li v-for="item in list" :key="item">{{ item }}</li>
- </ul>
- </div>
- </template>
-
- <script>
- export default {
- name: 'MintUI',
- data () {
- return {
- msg: 'Mint-UI',
- list:[]
- }
- },
- methods:{
- loadMore(){
- console.log(111111111111111);
- }
- }
- }
- </script>
-
- <style scoped>
- </style>
这里我们期望的效果就是,上拉触发loadMore方法,实验效果:
我们仿照官方网站的例子,写一个10行显示的效果,需要实现两点,第一点就是每次上拉扩充list数组,第二就是每一行按照“infinite-scroll-distance”参数的要求,每隔10个像素触发加载,所以一行至少是1个像素,要优化一下行间距,代码如下:
- <template>
- <div id="MintUI">
- <h1>{{msg}}</h1>
- <ul
- v-infinite-scroll="loadMore"
- infinite-scroll-disabled="loading"
- infinite-scroll-distance="10" class="list">
- <li v-for="item in list" :key="item">{{ item }}</li>
- </ul>
- </div>
- </template>
-
- <script>
- export default {
- name: 'MintUI',
- data () {
- return {
- msg: 'Mint-UI',
- list:[],
- loading:false,
- j:0
- }
- },
- methods:{
- loadMore(){
- this.loading = true;
- console.log(111111111111111);
- for(var i=0;i<20;i++,this.j++){
- this.list.push("第"+this.j+"条");
- }
- this.loading = false;
- }
- }
- }
- </script>
-
- <style scoped>
- .list li{
- height: 3.4rem;
- line-height: 3.4rem;
- border-bottom: 1px solid #000;
- font-size: 1.6rem;
- }
- </style>
效果:
可以看到满10条数据,就执行一次加载方法。
按照上面的写法,我们可以进行动态数据的填充,我们通过接口来扩充list数组,来实现加载真实网络API接口的效果。
上面是通过模拟数据实现的上拉分页,这里我们通过访问真实的API接口,获取数据,动态加载到页面上。
这里我们使用vue-resource来实现HTTP请求。
我们改造一下loadMore方法,请求网络数据。
- <template>
- <div id="MintUI">
- <h1>{{msg}}</h1>
- <ul
- v-infinite-scroll="loadMore"
- infinite-scroll-disabled="loading"
- infinite-scroll-distance="10" class="list">
- <li v-for="item in list" :key="item">{{ item.title }}</li>
- </ul>
- </div>
- </template>
-
- <script>
- export default {
- name: 'MintUI',
- data () {
- return {
- msg: 'Mint-UI',
- list:[],
- loading:false,
- page:1 //默认第一次请求第一页
- }
- },
- methods:{
- loadMore(){
- this.loading = true;
- this.requestData();
- this.loading = false;
- },
- requestData(){
- var api_url="http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page="+this.page;
- var that = this;//这里重新指定this 是因为在 then的内部不能使用Vue的实例化的this, 因为在内部 this 没有被绑定。
- //jsonp支持跨域请求,后台api接口也需要支持
- this.$http.jsonp(api_url).then(
- function(response){
- that.list=that.list.concat(response.body.result);//数组拼接
- this.page+=1;//下次加载下一页
- },function(err){
- console.log(err);
- }
- );
- }
- }
- }
- </script>
-
- <style scoped>
- .list li{
- height: 3.4rem;
- line-height: 3.4rem;
- border-bottom: 1px solid #000;
- font-size: 1.6rem;
- }
- </style>
这里我们添加了新闻列表的API接口请求,每次请求1页的数据。效果:
这里我们需要注意一个问题,因为我们请求新闻是异步请求,有可能出现在新闻的网络请求没有加载完,快速拉动列表的时候,又触发了新的加载,此时page还没来得及更新,会出现两次加载同一个数据的情况:
如何解决这个问题呢?很简单,我们在请求完成之前,不允许触发动态加载的方法,即我们将“loading”这个请求数据的开关,在加载完成之后再打开:
- methods:{
- loadMore(){
- this.requestData();
- },
- requestData(){
- this.loading = true;//关闭触发请求的开关
- var api_url="http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page="+this.page;
- var that = this;//这里重新指定this 是因为在 then的内部不能使用Vue的实例化的this, 因为在内部 this 没有被绑定。
- //jsonp支持跨域请求,后台api接口也需要支持
- this.$http.jsonp(api_url).then(
- function(response){
- that.list=that.list.concat(response.body.result);//数组拼接
- this.page+=1;//下次加载下一页
- if(response.body.result.length<20){//当请求数据是最后一页时
- this.loading = true;//最后一页时,关闭触发请求的开关
- that.list=that.list.concat({title:'没有数据了,已经到底......'});//到最后给用户一个提示
- }else{
- //当请求数据不是最后一页时
- this.loading = false;//加载完成后,打开触发请求的开关
- }
- },function(err){
- console.log(err);
- }
- );
- }
- }
这里还有一个细节,就是处理最后一页的问题,就是当拉到没有数据的时候,就不允许再拉了。
效果:
最后,为了让用户感觉有上拉的加载效果,我们在上拉的时候,显示正在加载的信息提示,这里在<ul>列表最后新增一个<div>标签,放置一个加载信息(也可以配上转圈的动画):
- <template>
- <div id="MintUI">
- <h1>{{msg}}</h1>
- <ul
- v-infinite-scroll="loadMore"
- infinite-scroll-disabled="loading"
- infinite-scroll-distance="10" class="list">
- <li v-for="item in list" :key="item">{{ item.title }}</li>
- </ul>
- <div>{{loadMsg}}</div>
- </div>
- </template>
-
- <script>
- export default {
- name: 'MintUI',
- data () {
- return {
- msg: 'Mint-UI',
- list:[],
- loading:false,
- page:1, //默认第一次请求第一页
- loadMsg:'加载中...'//加载信息
- }
- },
- methods:{
- loadMore(){
- this.requestData();
- },
- requestData(){
- this.loading = true;//关闭触发请求的开关
- var api_url="http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page="+this.page;
- var that = this;//这里重新指定this 是因为在 then的内部不能使用Vue的实例化的this, 因为在内部 this 没有被绑定。
- //jsonp支持跨域请求,后台api接口也需要支持
- this.$http.jsonp(api_url).then(
- function(response){
- that.list=that.list.concat(response.body.result);//数组拼接
- this.page+=1;//下次加载下一页
- if(response.body.result.length<20){//当请求数据是最后一页时
- this.loading = true;//最后一页时,关闭触发请求的开关
- this.loadMsg = '没有数据了,已经到底......';//修改加载信息,给用户一个提示
- }else{
- //当请求数据不是最后一页时
- this.loading = false;//加载完成后,打开触发请求的开关
- }
- },function(err){
- console.log(err);
- }
- );
- }
- }
- }
- </script>
-
- <style scoped>
- .list li{
- height: 3.4rem;
- line-height: 3.4rem;
- border-bottom: 1px solid #000;
- font-size: 1.6rem;
- }
- </style>
加载时效果:
加载到最后效果:
注:由于没有处理样式,很丑,见谅,有条件的童鞋可以进行相应的优化。
以上就是使用infinite-scroll实现上拉分页加载的全部内容。
参考:
《IT营:itying.com-2018年Vue2.x 5小时入门视频教程》
转载请注明出处:https://blog.csdn.net/acmman/article/details/111810692
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。