HOME> 华语世界杯> 90%的人都在用的下拉刷新,我把它拆了!

90%的人都在用的下拉刷新,我把它拆了!

华语世界杯 2025-11-23 05:29:43

你有没有在手机上刷微博、刷朋友圈、刷小红书的时候,手指从上往下拉一下,页面就自动刷新了?这就是我们常说的------下拉刷新功能。

今天,我们就来揭开它的神秘面纱,看看它是怎么用代码实现的。

一、下拉刷新到底是什么?

想象一下:你正在看一个笔记列表,突然想看看有没有新内容。于是你用手指从屏幕顶部往下拉,这时页面会:

向下移动(像被你拽下来一样)

显示"下拉刷新..." → "释放刷新..." → "加载中..."

松手后,重新加载新数据

加载完自动弹回去

这个过程,就是"下拉刷新"。

我们要做的,就是用代码模拟这个交互行为。

二、核心思路:四个关键步骤

整个下拉刷新组件的实现,可以分成 4 个步骤:

👉 监听用户的手指动作(触摸开始、移动、结束)

📊 管理状态(比如当前拉了多少距离)

🎨 实现动画效果(下拉和回弹)

🔗 和父组件通信(告诉它"该刷新数据啦!")

下面我们一个一个来看。

三、第一步:监听用户的手指操作

我们要知道用户什么时候开始拉、拉了多少、什么时候松手。这就要靠触摸事件。

1. onTouchStart:记录起始位置

js

复制代码

const onTouchStart = (e) => {

const start_y = e.touches[0].clientY

setStartY(start_y)

}

👉 解释:当用户手指刚碰到屏幕时,记录下触摸的Y坐标(比如是屏幕第500像素的位置),保存起来。

2. onTouchMove:计算下拉距离

js

复制代码

const onTouchMove = (e) => {

const move_y = e.touches[0].clientY

if (move_y < startY) return // 防止向上滑动也触发

setDistance(move_y - startY) // 当前拉了多少距离

setTranslateY(distance ** 0.8) // 控制页面下移多少(更自然)

if (distance >= 100) {

setCurrent('释放刷新...')

}

}

👉 解释:

用户一边拉,我们就一边计算他拉了多少(move_y - startY)。

我们不让页面跟着拉多少就下移多少,而是用了个"指数函数 "(distance ** 0.8),这样越拉越慢,手感更顺滑。

当拉到 100px 以上,就提示用户:"可以松手啦!"

3. onTouchEnd:松手后判断是否刷新

js

复制代码

const onTouchEnd = () => {

if (distance >= 100) {

setCurrent('加载中...')

// 开始回弹动画

timer = setInterval(() => {

setTranslateY(prev => prev - 5)

}, 20)

onLoad() // 调用父组件的加载函数

}

}

👉 解释:

用户松手时,如果拉的距离够长(≥100px),就认为"我要刷新"。

显示"加载中..."

启动一个定时器,每20毫秒让页面往上移5px,实现"慢慢弹回去"的动画。

同时调用 onLoad(),告诉父组件:"快去加载新数据吧!"

四、第二步:用状态管理记住关键数据

React 中用 useState 来保存各种状态:

js

复制代码

const [startY, setStartY] = useState(0) // 起始Y坐标

const [distance, setDistance] = useState(0) // 当前拉了多少

const [translateY, setTranslateY] = useState(0) // 页面下移多少

const [current, setCurrent] = useState('下拉刷新...') // 状态文字

这些变量就像"记忆",让程序知道现在处于什么阶段。

✅ 小知识:useState 是 React 的"状态钩子",可以让函数组件记住数据。

五、第三步:让页面动起来------动画效果

我们通过 CSS 的 transform: translateY() 来控制页面下移:

jsx

复制代码

{children}

translateY 越大,页面就越往下"飘"。

松手后,我们用 setInterval 每次减5px,直到回到顶部,实现平滑回弹。

还有一个细节:当页面快回到顶部时(比如 ≤40px),就清除定时器,防止无限执行:

js

复制代码

useEffect(() => {

if (translateY <= 40) {

clearInterval(timer)

}

}, [translateY])

✅ 这叫"副作用监听",useEffect 会自动检测 translateY 变化。

六、第四步:和外面的世界沟通------组件通信

我们的下拉组件是"通用"的,它不知道该加载什么数据。所以需要父组件告诉它:

jsx

复制代码

你的内容

onLoad:松手后要执行的函数(比如重新请求接口)

finished:加载是否完成

setFinished:用来重置状态

当数据加载完成后,父组件设置 setFinished(true),下拉组件收到后就会自动回到顶部:

js

复制代码

useEffect(() => {

if (finished) {

setTranslateY(0)

setFinished(false) // 重置,准备下次刷新

}

}, [finished])

✅ 这就是"父子组件通信",通过 props 传递函数和状态。

七、完整流程图解

scss

复制代码

用户下拉

onTouchStart 记录起点

onTouchMove 计算距离,更新UI

松手时 onTouchEnd 判断是否够长

够长?→ 显示"加载中" + 启动回弹动画 + 调用 onLoad()

onLoad() 请求新数据

数据加载完,父组件 setFinished(true)

Pull 组件收到,回到顶部,重置状态

模拟农场17中文版
华为畅享7用户指南 (SLA AL00&TL10,01,中文)