微信小程序自身有下拉刷新的动态效果,但是这个效果只针对page,如果需要只对其中的某个滚动的子元素做下拉的效果,是没法实现的,当然还有scroll-view,但是scroll-view在到达顶部和底部的时候比较生硬,没有回弹的效果,所以我就想有没有方法能实现这个回弹的效果。
我试了以下三种方法
1.使用better-scroll和mpvue
使用better-scroll插件,用vue的方式写滚动列表,实现了简单的下拉刷新上拉加载,better-scroll本身就有滚动回弹的效果,写完之后,在浏览器里看是没问题了,但是经过mpvue编译成小程序之后,初始化better-scroll对象的时候直接报错了,我估计是因为better-scroll有使用到dom对象,但是小程序里面是没有dom对象的,具体的原因我没有深究。
2.使用小程序的movable-view和scroll-view实现列表
使用movable-view,里面嵌套scroll-view,movable-view和scroll-view的宽高是一样的,这样使用的话是可以滚动的,但是在开发者工具里面没有回弹的效果,和直接使用scroll-view差不多,手机上倒是有滚动回弹的效果,这样开发的时候就没办法用了。
3.动态计算movable-view的高度
使用movable-view,movable-view里面只有一个直接子节点,一个普通的view,姑且称这个view为content,content不给高度,靠里面的元素来撑高,然后在onReady里面获取到content的高度,赋值给movable-view,是的movable-view的高度和content的高度一致,这样就可以了。上拉加载和下拉刷新主要是监听change事件,判断他的位置,当content的内容改变的时候,再重新获取一下content的高度赋值给movable-view即可。但是这个还有点问题,就是不能在app.json中使用usingComponents,也不能在页面的json文件里面使用这个属性,也就是不能使用自定义组件。具体问题还不知道为什么,可能是微信小程序的一个bug吧,使用了之后page的宽高和movable-view的位置会变得很奇怪。
下面是我的代码
<view class='container'>
<movable-area class='area'>
<movable-view class='view' style="height: {{h}}px;" direction="vertical" inertia out-of-bounds>
<view class='content'>
<view class='box' wx:for="{{list}}" wx:key="{{index}}">{{index}}</view>
</view>
</movable-view>
</movable-area>
</view>
page {
width: 100%;
height: 100%;
}
.container {
width: 100%;
height: 100%;
}
.box {
width: 100%;
height: 200rpx;
background-color: #FFEE00;
}
.area {
width: 100%;
height: 100%;
}
.view {
width: 100%;
}
Page({
data: {
isReseting: false //正在回弹
},
onLoad: function() {
let list = [];
for (let i = 0; i < 10; i++) {
list.push(i);
}
this.setData({
list
})
},
onReady: function() {
const query = wx.createSelectorQuery();
query.select('.area').boundingClientRect(res => {
this.data.areaH = res.height;
}).exec();
this.refresh();
},
refresh: function() {
const query = wx.createSelectorQuery();
query.select('.content').boundingClientRect(res => {
this.setData({
h: res.height
});
}).exec();
},
change: function (e) {
if (e.detail.source === 'out-of-bounds') {
if (e.detail.y < (this.data.areaH - this.data.h - 10)) {
//到达下拉刷新的条件
if (!this.data.isReseting) {
//控制在回弹钱不再触发
this.data.isReseting = true;
let list = [];
for (let i = 10; i < 20; i++) {
list.push(i);
}
this.setData({
list: this.data.list.concat(list)
})
this.refresh();
}
} else if (e.detail.y === 0) {
this.data.isReseting = false;
}
}
}
})