任何一个库在网上都褒贬不一,uni-app同样如此,对于不是太熟悉前端开发的人员来说使用这样一个库能让我们的开发效率提高不少,如果你想一套代码,发布到多个平台,那么uni-app也是一个很不错的选择。
如果你想了解更多关于uni-app的知识请自行官网查看,我这里今天只记录下一个关于上拉刷新和下拉加载的小功能。
其实关于加载更多这个插件,官方已经为我们提供了,放在扩展组件中,当然这个组件只是为我们实现了上拉加载的按钮显示样式,具体的获取数据逻辑还是需要我们自己去编写。
效果预览
转的图片有点大,没工夫找工具了。
![]()
分析数据结构
我们获取数据的逻辑是要根据目标接口返给我们的的数据结构来编写的,我们先来看下目标返回的大概结构。
我们放收尾和中间任意一页的数据结构给大家看。
第一页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| { "next": "http://127.0.0.1:8000/api/v1/lecture/?page=bz0z&size=3", "previous": null, "results": [ { "id": 80, "name": "完成能够阅读.", "start_time": "2020-09-27T16:35:46", "address": "江西省海口县上街贵阳街v座 930357", "thumbnail": "https://www.lorempixel.com/750/450", }, { "id": 79, "name": "规定更多系列密码其实.", "start_time": "2020-09-27T02:33:48", "address": "甘肃省秀英县合川周街a座 342016", "thumbnail": "https://placekitten.com/750/450", }, { "id": 78, "name": "能够应该首页免费.", "start_time": "2020-10-22T21:02:58", "address": "山东省洋县南湖吴街g座 247551", "thumbnail": "https://dummyimage.com/750x450", } ] }
|
第二页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| { "next": "http://127.0.0.1:8000/api/v1/lecture/?page=bz02&size=3", "previous": "http://127.0.0.1:8000/api/v1/lecture/?page=cj0xJnA9MTAw&size=3", "results": [ { "id": 77, "name": "价格觉得项目有限作品帮助.", "start_time": "2020-09-19T05:14:11", "address": "河北省莹县平山侯路H座 848604", "thumbnail": "https://placekitten.com/750/450", }, { "id": 76, "name": "这是他的因此因此.", "start_time": "2020-10-13T02:20:59", "address": "贵州省西安市淄川马路b座 421301", "thumbnail": "https://www.lorempixel.com/750/450", }, { "id": 74, "name": "其实一点发表科技事情.", "start_time": "2020-10-25T20:03:47", "address": "四川省凤英市门头沟张街B座 755654", "thumbnail": "https://dummyimage.com/750x450", } ] }
|
最后一页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| { "next": null, "previous": "http://127.0.0.1:8000/api/v1/lecture/?page=bz0zJnI9MQ%3D%3D&size=3", "results": [ { "id": 4, "name": "精华业务进入.", "start_time": "2020-11-03T01:30:23", "address": "云南省春梅市沙市银川路Y座 310692", "thumbnail": "https://www.lorempixel.com/750/450", }, { "id": 3, "name": "还有那么注意精华.", "start_time": "2020-09-26T22:04:27", "address": "新疆维吾尔自治区兰州县高坪王街v座 401585", "thumbnail": "https://dummyimage.com/750x450", }, { "id": 2, "name": "技术服务如此本站软件不要.", "start_time": "2020-09-28T12:23:53", "address": "北京市梅县城北成都路B座 221544", "thumbnail": "https://placekitten.com/750/450", } ] }
|
我这里要说明下,为了代码不那么长我们这里都是每页3条来显示的,实际项目中肯定每页不止3条。另外分析接口返回数据可以得知,页码是加密的,我们不知道下一页的页码是什么(接口服务用的django,其第三方包DjangoRestFramework中分页自带有这个功能),其他可以看出来的就是最后一页的next页为null,利用这点我觉得我们可以就依据这个下一页字段,没有下一页字段代表数据读取完了。
获取数据逻辑
初始化
默认进去该页面肯定会默认显示几条数据。我们可以在onload里直接编写一下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13
| uni.request({ url: "你的接口地址", success: (res) => { if (res.statusCode == 200) { this.list = res.data.results } else { console.log("出错了,联系管理员吧") } }, fail: (err) => { console.log("出错了,联系管理员吧") } })
|
生命周期
在uni-app页面生命周期中有一个onReachBottom,它就是负责页面上拉触底事件的处理函数。我们将刚才写的request请求写到一个方法中,方法名为get_list()
,生命周期onReachBottom中如下书写:
1 2 3
| onReachBottom() { this.get_list() },
|
优化获取数据逻辑
我们当然可以在上拉加载更多时重写写一个请求方法,但是为了代码复用,我们最好是在原来请求代码的数据上进行修改,毕竟待会儿下拉刷新页面的时候也要重新发起请求。
简单分析下流程:下拉页面请求新数据-》将新数据追加到老数据后面-》直到所有数据全部请求完。
在分析数据结构中我们可以得出没有下一页了即代码数据全部请求完了,我们来定义一个参数来存放下一页链接。
初步尝试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| <script> import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue' export default { data() { components: { uniLoadMore } return { list: [], status: 'more', contentText: { contentdown: '上拉加载更多', contentrefresh: '加载中', contentnomore: '没有更多' }, next_url: '' } }, onReachBottom() { this.get_lecture() }, onLoad() { this.get_list() }, methods: { get_list: function() { var url = `目标接口地址` if (this.next_url) { url = this.next_url }
uni.request({ url: url, success: (res) => { if (res.statusCode == 200) { this.list = this.list.concat(res.data.results) this.next_url = res.data.next } else { console.log("出错了,联系管理员吧") } }, fail: (err) => { console.log("出错了,联系管理员吧") } }) }, } } </script>
|
如果你看了代码不知道有没有发现其中的bug,我是没有发现,我是在预览页面时才发现了有问题的。
这个bug就是当你获取完所有的数据之后,又开始从第一篇文章开始获取了,因为所有页面获取完之后next_url的值为null了,所以又重新获取初始数据,所以我们要区分是第一次进来的还是数据加载完了。
我这里用了一个最Low的办法,初始的时候直接将next_url设为false了;正常该值为string的url链接;访问完所有数据next_url为null。区分下这三种状态就可以了。
代码优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| <script> import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue' export default { data() { components: { uniLoadMore } return { list: [], status: 'more', contentText: { contentdown: '上拉加载更多', contentrefresh: '加载中', contentnomore: '没有更多' }, next_url: false } }, onReachBottom() { this.satus = "more" this.get_list() }, onLoad() { this.get_list() }, methods: { get_list: function() { var url = `初始目标接口地址` if (this.next_url == false) { url = `初始目标接口地址` } else if (this.next_url == null) { url = null this.status = "noMore" return false } else { url = this.next_url }
uni.request({ url: url, success: (res) => { if (res.statusCode == 200) { this.list = this.list.concat(res.data.results) this.next_url = res.data.next } else { console.log("出错了,联系管理员吧") } }, fail: (err) => { console.log("出错了,联系管理员吧") } }) }, } } </script>
|
下拉刷新
相对于上拉加载更多,那么下拉刷新就简单的多了,无非是清空原有代码,初始化原始next_url为false,后面就跟第一次访问一样了,但是这其中包含两个要注意的点:
要使用下拉刷新需要在page页对应该页面的style属性中开启enablePullDownRefresh
即:
1 2 3 4 5 6
| { "path" : "页面链接", "style" : { "enablePullDownRefresh" : true } }
|
下拉刷新的时候有个旋转的动画,下拉之后它一直在旋转,我们需要在请求完成后手动结束这个动画
结束的方法为:uni.stopPullDownRefresh()
下拉刷新代码很简单,同样存在在页面生命周期中
1 2 3 4 5 6 7 8 9 10
| onPullDownRefresh() { this.list = [] this.next_url = false this.get_list()
},
|
全部代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| <template> <view> <view class="bg-white padding-lr-xs"> <navigator url="detail" class="flex" v-for="(item, index) in list" :key="item.id"> <view class="flex-sub margin-xs radius"> <image :src="item.thumbnail" class="lecture_img" mode="widthFix"></image> </view> <view class="flex-twice margin-xs lecture_text"> <view class="text-cut padding-bottom-xs"> {{item.id}}{{item.name}} </view> <view class="lecture_location"> <text class="cuIcon-location padding-right-sm"></text> {{item.address}} </view> <view class="lecture_date"> <text class="cuIcon-time padding-right-sm"></text> {{item.start_time}} </view>
</view> </navigator> <uni-load-more :status="status" :icon-size="16" :content-text="contentText" /> </view> </view> </template>
<script> import uniLoadMore from '@/components/uni-load-more/uni-load-more.vue' export default { data() { components: { uniLoadMore } return { list: [], status: 'more', contentText: { contentdown: '上拉加载更多', contentrefresh: '加载中', contentnomore: '没有更多' }, next_url: false } }, onPullDownRefresh() { this.list = [] this.next_url = false this.get_list()
}, onReachBottom() { this.status = 'more'; this.get_list() }, onLoad() { this.get_list() }, methods: { get_list: function() { var data = {} var url = `默认接口地址` if (this.next_url == false) { url = `默认接口地址` } else if (this.next_url == null) { url = null this.status = "noMore" return false } else { url = this.next_url }
uni.request({ url: url, success: (res) => { if (res.statusCode == 200) { this.list = this.list.concat(res.data.results) this.next_url = res.data.next uni.stopPullDownRefresh() } else { uni.showModal({ showCancel: false, content: "出错了,联系管理员吧" }) } }, fail: (err) => { console.log(err) uni.showModal({ showCancel: false, content: "出错了,联系管理员吧" }) } }) }, } } </script>
<style> .lecture_text { overflow: hidden; }
.lecture_img { width: 100%; }
.lecture_title { white-space: nowrap; text-overflow: ellipsis; padding-bottom: 10px; }
.lecture_location, .lecture_date { line-height: 20px; font-size: 12px; color: #AAAAAA; } </style>
|