用 Vue3 搭建抖音级无限滚动列表:完整机制指南 📅 发布时间:2026/9/15 11:11:55 👁 浏览次数: 用 Vue3 搭建抖音级无限滚动列表完整机制指南【免费下载链接】douyinVue3 Pinia 仿抖音Vue 在移动端的最佳实践 . Imitate TikTok Vue Best practices on Mobile项目地址: https://gitcode.com/GitHub_Trending/do/douyindouyin 项目是一个基于 Vue3 Pinia 的仿抖音信息流应用它的核心是一套可复用的无限滚动列表组件Scroll.vue 负责手势与滚动交互ScrollList.vue 负责分页数据配合 60px 预加载阈值和加载锁让信息流刷起来没有尽头。为什么信息流总停在点一下加载更多做 feed 类页面多数人第一版都会做成加载更多用户滑到屏幕末尾必须点一下按钮下一批数据才出现。这个动作打断了滑动节奏对短视频这种以不停刷为目标的场景是致命的。另一种常见做法是触底才请求结果就是手指碰到底的瞬间出现 loading 指示用户被迫原地等一小会儿内容衔接处出现明显卡顿。douyin 项目对移动端信息流给出的答案不同手指还没摸到列表底部下一批数据已经在路上。页面看起来无限延伸不存在任何加载按钮刷新则由下拉手势完成。项目地图两个组件的分工与三个配角滑一屏加载一批的全部逻辑集中在 src/components/ 目录核心是两个文件的两层分工Scroll.vue ——交互层。一个可滚动的容器组件监听 touchmove 与 scroll 事件既在顶部识别下拉手势并触发刷新事件又负责计算滚动位置是否到达预加载线。ScrollList.vue ——数据层。持有 pageNo、pageSize、total 三个变量调用外部传入的 api把结果追加进列表并判断没有更多数据。三个配角补齐体验闭环Loading.vue 是全屏 / 行内两种形态的加载指示器NoMore.vue 是底部暂时没有更多了提示useScroll.ts 负责 keep-alive 页面返回时恢复滚动位置。页面侧的真实接入可以看 Shop.vue、LongVideo.vue 和 Community.vue它们都只写了极少几行就挂上了整套能力。机制拆解60px 预加载阈值与加载锁 60px 预加载阈值加载下一页的触发条件不是触底而是接近底部。Scroll.vue 的scroll()方法在容器每次滚动时做一次比较scroll() { if (this.$attrs.onPulldown) { if (this.wrapper.scrollHeight - this.wrapper.clientHeight this.wrapper.scrollTop 60) { this.$emit(pulldown) } } }scrollHeight - clientHeight是可滚动的最大距离scrollTop 60是当前滚动位置加上 60px 余量。也就是说用户距离列表底部还有 60px 时pulldown事件就已经发出下一批数据与用户的滑动并行走完。等手指真正到底数据通常已就位视觉上不会露出加载空档——这个余量正是感觉不到加载的来源。加载锁与增量追加数据层的防护只用了两行代码。loadData()第一行if (state.loading) return用布尔加载锁把请求进行中的后续触发直接丢弃避免快速滑动时多个请求堆叠造成数据重复追加数据时用的是concat而不是整体替换function loadData() { if (state.loading) return state.pageNo getData() } // 请求成功后追加而非替换 state.list state.list.concat(res.data.list)还有一处细节请求前会先判断state.total ! 0 state.total state.list.length列表条数与后端返回的 total 相等就提前 return——没有更多不需要额外状态位由数据本身推出。体验细节三态反馈与性能处理三种状态三种提示初始加载列表为空时ScrollList 把full-loading传给 ScrollLoading 组件以全屏形态居中显示用户明确知道内容在准备中。滚动加载请求进行中行内 loading 指示器挂在内容末尾不遮挡已渲染的列表项。无更多数据total 与列表长度相等后NoMore.vue 显示暂时没有更多了滚动到底不再触发任何请求。当 Scroll 开启useRefresh时顶部还能完成下拉刷新scrollTop为 0 且手指继续下移时内容跟手位移并被限制在 10px 以内松手后发出refresh事件、pageNo 归零重新拉取第一页。减少无效开销的两个处理增量更新concat 只让新增条目产生 DOM 节点已渲染部分原地不动diff 开销最小低端机型上体感差异明显。滚动位置记忆useScroll.ts 在 onDeactivated 时记下wrapper.scrollToponActivated 时写回。切换 tab 再回来列表停在离开时的位置不会弹回顶部。最小上手示例三行挂上无限滚动 把请求函数传给api把条目模板写进插槽无限滚动列表即完成接入ScrollList :apifetchVideoList template #default{ list } VideoCard v-foritem in list :keyitem.id :videoitem / /template /ScrollList核心参数参数说明apiFunction入参为{ pageNo, pageSize }pageSize 默认 10需返回{ success, data: { list, total } }#default插槽接收当前渲染的 list自行定义条目结构useRefreshScroll 容器可选开关启用下拉刷新手势如果列表更长单页条数很多时 DOM 数量会线性增长可以把渲染层换成虚拟滚动只渲染可视区域ScrollList 的阈值触发与加载锁机制不受影响两者可以组合。如果要复用把 Scroll ScrollList 原样抽进公共包即可交互与数据职责分离意味着换业务只需替换api和条目模板不需要动滚动逻辑。douyin 项目证明了一套交互容器 数据控制器的两层拆分足以撑起抖音级别的信息流体验代码量小到可以逐行读懂。克隆下来从 ScrollList.vue 开始断点跟一遍请求链路是最快的学习方式。git clone https://gitcode.com/GitHub_Trending/do/douyin【免费下载链接】douyinVue3 Pinia 仿抖音Vue 在移动端的最佳实践 . Imitate TikTok Vue Best practices on Mobile项目地址: https://gitcode.com/GitHub_Trending/do/douyin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考