本文已参与「新人创作礼」活动,一起开启掘金创作之路
趟坑经历:
1、直接使用页面的onPullDownRefresh函数——但页面上有scroll-view组件时,事件冲突导致onPulldownRefresh不生效
——onPullDownRefresh在页面上无scroll-view可使用
2、自定义scroll-view的ontouchmove 事件和 touchend事件,在move超过一定距离时设置loading 值为true,塞入loading dom,执行刷新函数。刷新函数数据拿到后,设置loading态为false,dom消失。——问题是ios的scroll-view会存在橡皮筋弹性效果,自动回弹。而塞入dom的渲染来不及,导致出现卡顿效果。即使加动画也不行
——最好就是不要自己定义刷新
3、结合refresherTriggered和ontouchmove ,在move超过一定距离时设置trigged值为true,修改onRefresherRefresh为刷新函数。刷新结束后设置trigged为false。——奇怪的问题是若move的距离恰好在临界值附件,刷新之后设置了trigged为false,但loading态没有取消
4、最后直接用refresherThreshold设置位移值,超过了即onRefresherRefresh执行。
——最后的问题是Taro上没有修改loading态的api,直接修改背景颜色,但是dom不可以。小程序原生开发是可以的
最终代码实现
import React, { useState } from 'react';
import { View, ScrollView } from '@tarojs/components';
// import { AtActivityIndicator } from 'taro-ui'
import './RefreshScrollView.scss';
export default function RefreshScrollView(props) {
const { refresh = null, loadMore = null, classNameAdditional = '' } = props;
const [loading, setLoading] = useState(false);
const onRefresh = () => {
setLoading(true);
refresh && refresh(endLoading);
};
const endLoading = () => {
setTimeout(() => {
setLoading(false);
}, 500);
};
const loadRecommend = () => {
loadMore && loadMore();
};
return (
<View className="dragUpdataPage">
<ScrollView
className={'home__wrap ' + classNameAdditional}
onScrollToLower={() => loadRecommend()}
scrollWithAnimation
refresherEnabled
refresherTriggered={loading}
onRefresherRefresh={onRefresh}
refresherThreshold={45}
scrollY
>
{props.childComponent}
</ScrollView>
</View>
);
import React, { useState } from 'react';
import { View, ScrollView } from '@tarojs/components';
// import { AtActivityIndicator } from 'taro-ui'
import './RefreshScrollView.scss';
export default function RefreshScrollView(props) {
const { down = null, loadMore = () => {}, classNameAdditional = '', loadingComponent = null } = props;
//1、用于将下拉高度定义为用户滑动高度的,需求暂时用不上;
// 2 、小于最小高度展示下拉刷新,到达后展示释放刷新,需求也用不上;
const [topClass, setTopClass] = useState('');
const [heightClass, setHeightClass] = useState('');
// const [downText, setDownText] = useState('下拉刷新')
const [scrollY, setScrollY] = useState(true);
const [dragState, setDragState] = useState(0); // 0不做操作 1刷新
const [startP, setStartP] = useState({});
const touchmove = (e) => {
const move_p = e.touches[0], //移动时的位置
deviationX = 0.3, //左右偏移量(超过这个偏移量不执行下拉操作)
deviationY = 56; //拉动长度(低于这个值的时候不执行)
const start_x = startP.clientX,
start_y = startP.clientY,
move_x = move_p.clientX,
move_y = move_p.clientY;
const dev = Math.abs(move_x - start_x) / Math.abs(move_y - start_y);
if (dev < deviationX) {
//当偏移数值大于设置的偏移数值时则不执行操作
if (move_y - start_y > 0) {
//下拉操作
const pY = Math.abs(move_y - start_y) / 3.5;
if (pY >= deviationY) {
down && setDragState(1);
down && setScrollY(false);
}
}
}
};
const touchEnd = (e) => {
if (dragState === 1) {
setHeightClass(' animateHeight ');
setTopClass(' animateTop ');
_down();
}
};
const _down = () => {
down(reduction);
};
const reduction = () => {
// 刷新之后重置
setTimeout(() => {
setHeightClass(' animateBackHeight ');
setTopClass(' animateBackTop ');
setScrollY(true);
setDragState(0);
}, 500);
};
const touchStart = (e) => {
setStartP(e.touches[0]);
};
// console.log(info)
const loadRecommend = () => {
loadMore();
};
return (
<View className="dragUpdataPage">
<View className={'downDragBox ' + heightClass}>{loadingComponent}</View>
<ScrollView
className={'home__wrap ' + topClass + classNameAdditional}
scrollY={scrollY}
onTouchMove={touchmove}
onTouchEnd={touchEnd}
onTouchStart={touchStart}
onScrollToLower={() => loadRecommend()}
scrollWithAnimation
>
{props.childComponent}
</ScrollView>
</View>
);
}