uniapp页面下拉刷新
Posted 哇哦Q
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uniapp页面下拉刷新相关的知识,希望对你有一定的参考价值。
目录
一、全局
修改pages.json的"enablePullDownRefresh": true,
"pages": [
"path": "pages/tabBar/dashboard/index",
"style":
"navigationBarTitleText": "项目管理",
"enablePullDownRefresh": true,
"navigationBarTextStyle": "white",
"navigationBarBackgroundColor": "#374449"
,
],
"globalStyle":
"navigationBarTextStyle": "black",
"navigationBarTitleText": "管理平台",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
,
页面中(onPullDownRefresh 处理函数和onLoad等生命周期函数同级 )
export default
data()
return
productList: [], //列表
query:
keyword: '', //搜索框
pagesize: 10,
page: 1,
,
total: 0, //总条数
showTotal: true, //是否显示“下拉加载更多~”
,
// 下拉刷新
onPullDownRefresh()
var allTotal = this.query.page * this.query.pagesize
//this.page为加载次数,this.pageSize为每一次加载的数据条数
if (allTotal < this.total)
//this.total为请求数据的总条数。只要现有条数小于总条数就执行一下代码
this.showTotal = true;
this.query.page++;
//加载次数递加
this.getlist() //请求更多数据列表
else
this.showTotal = false;
uni.stopPullDownRefresh();//停止刷新
,
二、局部
我使用的是插件https://ext.dcloud.net.cn/plugin?id=343
插件文档https://www.mescroll.com/uni.html
这个插件的还有相对应的案例我已经下载下来了,到时候直接放到编辑器打开即可 链接:https://pan.baidu.com/s/1q6IB-mCdCQqcvKaZmzJtcg 提取码:e66j
我的需求是顶部内容固定不动,列表下拉刷新(没有页码,数据一次性展示)
1、一个页面一个下拉刷新
页面使用
<template>
<view class="details-container">
<view class="example-body">
<view v-for="(item,index) in tags" :key="index"
:class="whichSelected===index?'stateBtnSelected':'stateBtnNoselect'" :circle="true"
@click="selectState(index)">item</view>
</view>
<view class="center" v-show="tabs===0">
<!-- 第一步:参数一个都不能少,三个事件是固定的 -->
<mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback"
:down="downOption" :up="upOption">
<Tree :list="list" :local='local'></Tree>
</mescroll-body>
</view>
</view>
</template>
<script>
import Tree from '../../components/Tree/index.vue'
//第二步:引入
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
export default
mixins: [MescrollMixin],//第二步:引入
name: 'Details',
components:
Tree,
,
data()
return
tags: [],
whichSelected: 0, //标签
tabs: 0, //标签对应页面
list: [], //列表
content: , //上一页数据
local: '',
//第三步:数据
//downOption和upOption的参数配置在mescroll-uni.js中查看
downOption:
auto: false // 不自动加载 (mixin已处理第一个tab触发downCallback)
,
upOption:
use: false, // 是否启用上拉加载; 默认true
auto: false
;
,
onLoad(e)
let that = this
this.local = uni.getLocale()
this.content = JSON.parse(e.item)
if (this.local === 'zh-Hans')
uni.setNavigationBarTitle(
title: that.content.Name,
)
else
uni.setNavigationBarTitle(
title: that.content.Name_EN,
)
this.GetFileListById()
this.tags.push(this.$t('word.whole'))
,
methods:
//第三步:事件
/*下拉刷新的回调 */
downCallback()
let that = this
this.api.GetFileListById( //调用接口
datagramsid: that.content.Id
).then(res =>
that.list = res.data.Data
this.$nextTick(() =>
this.mescroll.endSuccess(this.list.length)
)
).catch(() =>
//联网失败, 结束加载
this.mescroll.endErr();
)
,
/*上拉 */
upCallback()
let that = this
this.api.GetFileListById( //调用接口
datagramsid: that.content.Id
).then(res =>
that.list = res.data.Data
let curPageLen = this.list.length;
// 接口返回的是否有下一页 (true/false)
let hasNext = false;
setTimeout(() =>
this.mescroll.endSuccess(curPageLen, hasNext)
, 20)
).catch(() =>
//联网失败, 结束加载
this.mescroll.endErr();
)
,
GetFileListById()
let that = this
this.api.GetFileListById(
datagramsid: that.content.Id
).then(res =>
that.list = res.data.Data
)
,
</script>
2、一个页面多个下拉刷新(切换时滚动条回到顶部)
多页tabs切换,实现下拉刷新(没有页码,数据一次性展示) ,每个tab页面内容都不相同
插件上说不能使用v-if,是因为使用了v-if就不能实现切换tabs恢复滚动条位置(v-if是创建和销毁,v-show是隐藏和显示)。
但是我使用官方示例的代码重新加载列表数据或其他的方法都不行
// 详情返回列表,重新加载列表数据 onShow() this.canReset && this.mescroll.resetUpScroll() // 重置列表数据为第一页 this.canReset && this.mescroll.scrollTo(0,0) // 重置列表数据为第一页时,建议把滚动条也重置到顶部,避免无法再次翻页的问题 this.canReset = true // 过滤第一次的onShow事件,避免初始化界面时重复触发upCallback, 无需配置auto:false // 注意: 子组件没有 onShow 的生命周期, 所以 // 对于 mescroll-more.vue 和 mescroll-swiper.vue 的返回刷新, 需更新 1.3.3 版本, 且参考对应示例的onShow写法
若是换成mescroll-body,并且使用v-show会出现切换tabs滚动条位置一致,也就是上一页滚动条在哪,下一页的滚动条就在哪。找了好久也不知道问题出在哪里,最后我只能写成组件使用mescroll-uni+v-if的方法。
但是你们使用还是要先根据官网来做,如果出现我这样的问题再安装我的方法做
第一步:创建组件放置tabs所对应的页面(这里我就只写一个子组件的格式)
pages/word/components/all.vue
注意:子组件使用onShow、onLoad无效,需要写在created中才行
<template>
<!-- 不能用v-if (i: 每个tab页的专属下标; index: 当前tab的下标; 申明在 MescrollMoreItemMixin )-->
<view v-if="i === index">
<mescroll-uni ref="mescrollRef0" top="92" @init="mescrollInit" @down="downCallback" @up="upCallback"
:down="downOption" :up="upOption">
<!-- 数据列表 -->
<Tree :list="list" :local='local'></Tree>
</mescroll-uni>
</view>
</template>
<script>
import Tree from '@/components/Tree/index.vue'
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
import MescrollMoreItemMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more-item.js";
export default
mixins: [MescrollMixin, MescrollMoreItemMixin], // 使用mixin (在main.js注册全局组件)
components:
Tree,
,
props:
i: Number, // 每个tab页的专属下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
index: // 当前tab的下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
type: Number,
default ()
return 0
,
tabs: // 为了请求数据,演示用,可根据自己的项目判断是否要传
type: Array,
default ()
return []
,
data()
return
list: [], //下载列表
local: '',
downOption:
auto: false // 不自动加载 (mixin已处理第一个tab触发downCallback)
,
upOption:
use: false, // 是否启用上拉加载; 默认true
auto: false
,
created()
this.local = uni.getLocale()
,
methods:
/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
downCallback()
this.mescroll.resetUpScroll()
,
upCallback(page)
let pageNum = page.num
this.api.GetFileTreeJson().then(res =>
// console.log(res.data.Data)
this.list = res.data.Data
this.mescroll.endByPage(this.list.length, 1);
//设置列表数据
if (page.num == 1) this.list = []; //如果是第一页需手动制空列表
this.list = this.list.concat(res.data.Data); //追加新数据
).catch(() =>
//联网失败, 结束加载
this.mescroll.endErr();
)
,
</script>
pages/word/components/downitem.vue和上一个组件一致,只不过数据组件不一致,多了一个获取列表的方法给父组件使用
<template>
<!-- 不能用v-if (i: 每个tab页的专属下标; index: 当前tab的下标; 申明在 MescrollMoreItemMixin )-->
<view v-if="i === index">
<mescroll-uni ref="mescrollRef1" @init="mescrollInit" top="92" :down="downOption" @down="downCallback"
:up="upOption" @up="upCallback" @emptyclick="emptyClick">
<DownTree :records="records" :local='local'></DownTree>
</mescroll-uni>
</view>
</template>
<script>
import DownTree from '@/components/DownTree/index.vue'
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
import MescrollMoreItemMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more-item.js";
export default
mixins: [MescrollMixin, MescrollMoreItemMixin],
components:
DownTree
,
props:
i: Number, // 每个tab页的专属下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
index: // 当前tab的下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
type: Number,
default ()
return 0
,
tabs: // 为了请求数据,演示用,可根据自己的项目判断是否要传
type: Array,
default ()
return []
,
data()
return
records: [], //下载列表
local: '',
downOption:
auto: false // 不自动加载 (mixin已处理第一个tab触发downCallback)
,
upOption:
use: false, // 是否启用上拉加载; 默认true
auto: false
,
created()
this.local = uni.getLocale()
,
methods:
/*下拉刷新的回调 */
downCallback()
this.mescroll.resetUpScroll()
,
upCallback(page)
let pageNum = page.num
this.api.GetWxUserDownloadList().then(res =>
this.records = res.data.Data
this.mescroll.endByPage(this.records.length, 1);
//设置列表数据
if (page.num == 1) this.records = []; //如果是第一页需手动制空列表
this.records = this.records.concat(res.data.Data); //追加新数据
).catch(() =>
//联网失败, 结束加载
this.mescroll.endErr();
)
,
getrecords()
this.api.GetWxUserDownloadList().then(res =>
this.records = res.data.Data
this.mescroll.endByPage(this.records.length, 1);
//设置列表数据
if (page.num == 1) this.records = []; //如果是第一页需手动制空列表
this.records = this.records.concat(res.data.Data); //追加新数据
).catch(() =>
//联网失败, 结束加载
this.mescroll.endErr();
)
,
</script>
第三步:在页面中使用pages/word/components/index.vue
<template>
<view class="word-container">
<view class="example-body">
<view v-for="(item,index) in tags" :key="index"
:class="tabIndex===index?'stateBtnSelected':'stateBtnNoselect'" :circle="true"
@click="tabChange(index)" @input="changeload" v-model="tabIndex">item</view>
</view>
<!-- 全部 -->
<mescroll-all ref="mescrollItem0" :i="0" :index="tabIndex" :tabs="tags">
</mescroll-all>
<!-- 下载记录 -->
<MescrollDown ref="mescrollItem1" :i="1" :index="tabIndex" :tabs="tags">
</MescrollDown>
</view>
</template>
<script>
import MescrollAll from "./components/all.vue";
import MescrollDown from "./components/downitem.vue";
import MescrollMoreMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more.js";
export default
mixins: [MescrollMoreMixin],
name: 'Word',
components:
MescrollDown,
MescrollAll,
,
data()
return
tags: [],
local: '',
tabIndex: 0,//标签对应页面
;
,
onLoad()
this.tags.push(this.$t('word.whole'), this.$t('word.download'))
uni.setNavigationBarTitle(
title: this.$t('pages.word'),
)
,
onShow()
this.tabIndex = this.$store.state.tabs
this.local = uni.getLocale()
if (this.whichSelected === 1)
const Token = uni.getStorageSync('GetPhone_Token')
if (Token)
//点击下载列表tab的时候要判断有没有token,没有就要跳转到登录页,我登录成功后返回到这一页
//若是我不调用子组件的方法也就是获取列表数据,会出现一直显示加载中,所以我这里调用了方法,下面的标签切换同理
this.$refs.mescrollItem1.getrecords()
else
uni.navigateTo(
url: '/pages/login/index'
);
,
methods:
// 标签切换
tabChange(index)
this.whichSelected = index
this.tabIndex = index
this.$store.commit('SET_TABS', index)
if (this.tabIndex === 1)
const Token = uni.getStorageSync('GetPhone_Token')
if (Token)
this.$refs.mescrollItem1.getrecords()
else
uni.navigateTo(
url: '/pages/login/index'
);
,
</script>
<style lang="scss">
.vue-ref
padding: 0 !important;
.word
&container
position: relative;
.left
display: flex;
margin: 10px;
.example-body
display: flex;
padding: 10px 20px;
background-color: #fff;
width: 100%;
position: fixed;
z-index: 2;
.center
position: absolute;
top: 45px;
width: 100%;
// height: 100%;
border-top: 1px solid #e5e5e5;
.stateBtnSelected
background-color: #bbe5ff;
color: #1480cd !important;
border-radius: 20px;
font-size: 14px;
height: 25px;
line-height: 25px;
// width: 60px;
margin: 0 5px;
padding: 0 15px;
text-align: center;
.stateBtnNoselect
background-color: transparent;
color: #8f939c !important;
border: none !important;
font-size: 14px;
height: 25px;
line-height: 25px;
// width: 60px;
margin: 0 5px;
padding: 0 15px;
text-align: center;
.slot-image
width: 30px;
height: 30px;
.slot-box
margin-right: 10px;
.uni-list-item__container
align-items: center !important;
line-height: 20px;
</style>
3、一个页面多个下拉刷新(切换时恢复滚动条位置)
如果tabs对应内容分别封装成各自组件,子组件封装的时候使用mescroll-uni,并且使用v-show会出现当列表数据多页时切换tabs,恢复滚动条位置不准确并且会触发上拉这样的问题。但是如果我把他放在一个组件里就不会产生这样的问题
第一步:组件pages/word/components/all.vue
Tree和DownTree组件使用的是uni-list的自定义插槽,不知道为啥我使用uni-list-item就会触发一次上拉,之后就不会了,但是不使用就不会触发
<template> <view class="word-container"> <!-- 使用这个切换tabs的时候,会触发上拉一次,之后就不会再触发了 --> <!-- <uni-list> <uni-list-item v-for="(item,index) in records" :key='index' :title="local==='zh-Hans'?item.filename:item.filename_EN" thumb-size="lg" :rightText="item.DownloadTime"> <template v-slot:header> <view class="slot-box"> <image v-if="item.fileExt==='.mp4'" class="slot-image" src="/static/shipin_lvhangyingxiang.png" mode="widthFix"> </image> <image v-else-if="item.fileExt==='.pdf'" class="slot-image" src="/static/pdfwenjian.png" mode="widthFix"> </image> <image v-else class="slot-image" src="/static/a-wenjianjiawenjian.png" mode="widthFix"> </image> </view> </template> </uni-list-item> </uni-list> --> <uni-list v-for="(item,j) in records" :key='j'> <view :border="none" :padding="0" :spacing="0" style="padding:0" :is-shadow="false" :isFull="true"> <view class="card-title" style="display: flex;justify-content: space-between;"> <view> <image v-if="item.fileExt==='.mp4'" class="slot-image" src="/static/shipin_lvhangyingxiang.png" mode="widthFix"> </image> <image v-else-if="item.fileExt==='.pdf'" class="slot-image" src="/static/pdfwenjian.png" mode="widthFix"> </image> <image v-else class="slot-image" src="/static/a-wenjianjiawenjian.png" mode="widthFix"> </image> </view> <view class="title-box" style="display: flex;justify-content: space-between;width: 100%;align-items: center;"> <view class="">local==='zh-Hans'?item.filename:item.filename_EN </view> <view class="">item.DownloadTime</view> </view> </view> </view> </uni-list> </view> </template>
<template>
<!-- 不能用v-if (i: 每个tab页的专属下标; index: 当前tab的下标; 申明在 MescrollMoreItemMixin )-->
<view v-show="i === index">
<mescroll-uni :ref="'mescrollRef'+i" top="92" @init="mescrollInit" @down="downCallback" @up="upCallback"
:down="downOption" :up="upOption">
<!-- 数据列表 -->
<!-- tab为0的时候 -->
<Tree v-if="index===0" :list="list" :local='local'></Tree>
<!-- tab为1的时候 -->
<DownTree v-else :records="records" :local='local'></DownTree>
</mescroll-uni>
</view>
</template>
<script>
import DownTree from '@/components/DownTree/index.vue'
import Tree from '@/components/Tree/index.vue'
import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
import MescrollMoreItemMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more-item.js";
export default
mixins: [MescrollMixin, MescrollMoreItemMixin], // 使用mixin (在main.js注册全局组件)
components:
Tree,
DownTree
,
props:
i: Number, // 每个tab页的专属下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
index: // 当前tab的下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
type: Number,
default ()
return 0
,
tabs: // 为了请求数据,演示用,可根据自己的项目判断是否要传
type: Array,
default ()
return []
,
data()
return
list: [], //下载列表
local: '',
records: [], //下载列表
downOption:
auto: false // 不自动加载 (mixin已处理第一个tab触发downCallback)
,
upOption:
use: false, // 是否启用上拉加载; 默认true
auto: false
,
created()
this.local = uni.getLocale()
,
methods:
/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
downCallback()
this.mescroll.resetUpScroll()
,
upCallback(page)
if (this.index === 0)
let pageNum = page.num
this.api.GetFileTreeJson().then(res =>
// console.log(res.data.Data)
this.list = res.data.Data
this.mescroll.endByPage(this.list.length, 1);
//设置列表数据
if (page.num == 1) this.list = []; //如果是第一页需手动制空列表
this.list = this.list.concat(res.data.Data); //追加新数据
).catch(() =>
//联网失败, 结束加载
this.mescroll.endErr();
)
else
this.api.GetWxUserDownloadList().then(res =>
// console.log(res.data.Data)
this.records = res.data.Data
this.mescroll.endByPage(this.records.length, 1);
//设置列表数据
if (page.num == 1) this.records = []; //如果是第一页需手动制空列表
this.records = this.records.concat(res.data.Data); //追加新数据
).catch(() =>
//联网失败, 结束加载
this.mescroll.endErr();
)
,
// 文件列表
GetFileTreeJson()
this.api.GetFileTreeJson().then(res =>
// console.log(res.data.Data)
this.list = res.data.Data
this.mescroll.endByPage(this.list.length, 1);
//设置列表数据
if (page.num == 1) this.list = []; //如果是第一页需手动制空列表
this.list = this.list.concat(res.data.Data); //追加新数据
).catch(() =>
//联网失败, 结束加载
this.mescroll.endErr();
)
,
getrecords()
this.api.GetWxUserDownloadList().then(res =>
// console.log(res.data.Data)
this.records = res.data.Data
this.mescroll.endByPage(this.records.length, 1);
//设置列表数据
if (page.num == 1) this.records = []; //如果是第一页需手动制空列表
this.records = this.records.concat(res.data.Data); //追加新数据
).catch(() =>
//联网失败, 结束加载
this.mescroll.endErr();
)
,
</script>
第二步:页面使用pages/word/components/index.vue
<template>
<view class="word-container">
<view class="example-body">
<view v-for="(item,index) in tags" :key="index"
:class="tabIndex===index?'stateBtnSelected':'stateBtnNoselect'" :circle="true"
@click="tabChange(index)" @input="changeload" v-model="tabIndex">item</view>
</view>
<mescrollItem0 ref="mescrollItem0" :i="0" :index="tabIndex" :tabs="tags">
</mescrollItem0>
<mescrollItem0 ref="mescrollItem1" :i="1" :index="tabIndex" :tabs="tags">
</mescrollItem0>
</view>
</template>
<script>
import mescrollItem0 from "./components/all.vue";
import mescrollItem1 from "./components/downitem.vue";
// import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
import MescrollMoreMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more.js";
export default
mixins: [MescrollMixin],
name: 'Word',
components:
mescrollItem0,
mescrollItem1,
,
data()
return
tags: [],
list: [],
records: [], //下载列表
local: '',
tabIndex: 0,//标签对应页面
;
,
onLoad()
this.tags.push(this.$t('word.whole'), this.$t('word.download'))
uni.setNavigationBarTitle(
title: this.$t('pages.word'),
)
,
onShow()
this.whichSelected = this.$store.state.tabs
this.tabIndex = this.$store.state.tabs
this.local = uni.getLocale()
if (this.whichSelected === 1)
const Token = uni.getStorageSync('GetPhone_Token')
if (Token)
this.$refs.mescrollItem1.getrecords()
else
uni.navigateTo(
url: '/pages/login/index'
);
,
methods:
// 标签切换
tabChange(index)
this.whichSelected = index
this.tabIndex = index
this.$store.commit('SET_TABS', index)
if (this.tabIndex === 1)
const Token = uni.getStorageSync('GetPhone_Token')
if (Token)
this.$refs.mescrollItem1.getrecords()
else
uni.navigateTo(
url: '/pages/login/index'
);
,
</script>
<style lang="scss">
.vue-ref
padding: 0 !important;
.word
&container
position: relative;
.left
display: flex;
margin: 10px;
.example-body
display: flex;
padding: 10px 20px;
background-color: #fff;
width: 100%;
position: fixed;
z-index: 2;
.center
position: absolute;
top: 45px;
width: 100%;
// height: 100%;
border-top: 1px solid #e5e5e5;
.stateBtnSelected
background-color: #bbe5ff;
color: #1480cd !important;
border-radius: 20px;
font-size: 14px;
height: 25px;
line-height: 25px;
// width: 60px;
margin: 0 5px;
padding: 0 15px;
text-align: center;
.stateBtnNoselect
background-color: transparent;
color: #8f939c !important;
border: none !important;
font-size: 14px;
height: 25px;
line-height: 25px;
// width: 60px;
margin: 0 5px;
padding: 0 15px;
text-align: center;
.slot-image
width: 30px;
height: 30px;
.slot-box
margin-right: 10px;
.uni-list-item__container
align-items: center !important;
line-height: 20px;
</style>
uni-app 小程序实现下拉刷新
参考技术A page.json 里面配置该页面 enablePullDownRefresh 为 true 。页面里面增加 onPullDownRefresh 函数,监听该页面用户下拉刷新事件。·
本以为这样就大功告成了!在手机端一试,下拉刷新顶部的三个点一直不消失,始终都在刷新,是不是需要手动停止刷新?一看 API ,果然:
以上是关于uniapp页面下拉刷新的主要内容,如果未能解决你的问题,请参考以下文章