vue3中文字滚动代码
一、功能概述
该段 TS/Vue3 代码实现容器自动匀速滚动功能,具备以下核心特性:
页面加载后自动向下滚动容器;
用户手动操作容器(鼠标滚轮、拖动滚动条)立即停止自动滚动;
滚动到达底部 / 超时自动终止滚动定时器;
基于 setInterval 步进式平滑滚动,可调节滚动速度;
使用标识位区分「程序自动滚动」和「用户手动交互」,避免冲突。
依赖说明:
Vue3 API:nextTick、ref(scTop 为容器 DOM ref)
原生定时器:setInterval / clearInterval
TS 类型约束:区分数字 / 空定时器标识
二、完整源码
typescript
运行
// 全局定时器标识,存储滚动计时器ID,null代表无计时器
let scrollInterval: number | null = null;
// 用户交互标记:true=用户手动操作过滚动,终止自动滚动
let userInteracted = false;
/**
* 停止自动滚动统一方法
* 触发场景:用户滚轮/拖动滚动条、滚动到达终点、滚动超时
*/
const stopScroll = () => {
// 标记用户已交互,永久阻止后续自动滚动
userInteracted = true;
// 存在定时器则清除,并置空标识
if (scrollInterval !== null) {
clearInterval(scrollInterval);
scrollInterval = null;
}
};
/**
* 启动容器自动向下滚动逻辑
* @description 步进式持续滚动,满足终止条件则自动销毁定时器
*/
const handleScroll = () => {
// 终止条件1:用户已经手动操作过 || 容器DOM不存在,直接退出不启动滚动
if (userInteracted || !scTop.value) return;
// 获取滚动初始位置、滚动最大底部边界
let startPosition = scTop.value.scrollTop;
// 容器可滚动总高度 = 内容总高度 - 容器可视高度
let endPosition = scTop.value.scrollHeight - scTop.value.clientHeight;
// 滚动步长计数器,同时用作超时阈值
let h = 1;
// 创建定时滚动任务,保存定时器ID
scrollInterval = window.setInterval(() => {
// 终止条件2:用户交互 || 滚动步数超限(超时保护,防止死循环)
if (userInteracted || h > 1000) {
if (scrollInterval !== null) {
clearInterval(scrollInterval);
scrollInterval = null;
}
return;
}
// nextTick 等待DOM更新完成后修改滚动位置,保证渲染同步
nextTick(() => {
if (scTop.value) {
// 每次滚动偏移量 = 基础位置 + 步数 * 单步像素
scTop.value.scrollTop = startPosition + h * 3;
}
});
// 步数自增,控制滚动距离
h++;
}, 10); // 定时器间隔(ms):数值越小滚动越顺滑、速度越快
};
三、变量逐行详解
1. scrollInterval: number | null = null
类型:数字 / 空
作用:存储 setInterval 返回的计时器 ID,用于手动清除滚动;
初始值 null:代表当前无运行中的滚动定时器;
设计目的:防止重复创建多个定时器,避免滚动加速、抖动 bug。
2. userInteracted = false
布尔标记,核心交互拦截标识;
false:未手动操作,允许自动滚动执行;
true:用户操作过滚动,永久停止自动滚动,不会再次触发;
触发变为 true 的唯一入口:stopScroll() 函数。
四、函数详细解析
4.1 stopScroll () 停止滚动工具函数
执行逻辑
将 userInteracted 置为 true,永久屏蔽自动滚动;
判断定时器存在,执行 clearInterval 销毁定时任务;
将 scrollInterval 重置为 null,释放标记。
调用时机
监听容器 wheel / scroll / mousedown 事件,用户拖动滚动条、滑动鼠标时调用;
滚动逻辑内部满足终止条件时自调用清除定时器。
4.2 handleScroll () 启动自动滚动入口
前置拦截(函数开头判断)
typescript
运行
if (userInteracted || !scTop.value) return;
userInteracted:用户操作过,直接放弃启动;
!scTop.value:容器 DOM 元素未挂载(ref 为空),无法执行滚动,直接退出。
滚动边界变量
typescript
运行
let startPosition = scTop.value.scrollTop;
let endPosition = scTop.value.scrollHeight - scTop.value.clientHeight;
scrollTop:容器当前滚动垂直偏移;
scrollHeight:容器内部全部内容高度;
clientHeight:容器可视区域高度;
endPosition:滚动能到达的最底部像素值。
步长计数器 h
初始 h=1,每轮定时器 + 1;
双重作用:
计算滚动偏移:h * 3 控制每次向下滚动 3 像素;
超时保护:h > 1000 强制终止定时器,防止页面无限滚动、内存泄漏。
setInterval 定时滚动核心
typescript
运行
scrollInterval = window.setInterval(() => {}, 10)
间隔 10ms 执行一次滚动更新;
调参说明:
间隔时间越小 → 滚动越顺滑、速度越快;
间隔时间越大 → 滚动卡顿、速度变慢。
nextTick 作用
Vue DOM 更新异步,修改 scrollTop 放入 nextTick 回调,确保 DOM 渲染完成后再赋值,避免滚动不生效、位置错乱。
滚动位移公式
typescript
运行
scTop.value.scrollTop = startPosition + h * 3;
startPosition:滚动启动瞬间的初始位置;
h * 3:每帧累加 3 像素向下滚动;
修改数字 3 可调节滚动速度:数值越大单次滚动距离越大,滚动越快。
定时器内部终止判断
typescript
运行
if (userInteracted || h > 1000)
满足任一条件立即清除定时器:
用户手动滚动;
循环步数超过 1000 次,安全兜底终止。
五、配套使用示例(补充完整调用代码)
1. Vue 模板容器
vue
<template>
<!-- 可滚动容器,绑定ref,监听用户交互事件 -->
<div
ref="scTop"
@wheel="stopScroll"
@mousedown="stopScroll"
style="height: 400px; overflow-y: auto;"
>
大量超长内容...
</div>
</template>
2. script ref 定义与触发滚动
typescript
运行
import { ref, nextTick, onMounted } from 'vue'
// 容器DOM绑定
const scTop = ref<HTMLDivElement | null>(null)
// 页面挂载完成启动自动滚动
onMounted(() => {
handleScroll()
})
六、参数调优指南
滚动快慢调节
单次滚动像素:修改 h * 3 中数字,改为 5 更快,1 更慢更顺滑;
定时器间隔:修改 10,5 毫秒更快,20 毫秒更平缓。
超时保护时长
h > 1000:间隔 10ms 时,1000 次 = 10 秒自动停止,可按需修改数值。
是否允许重新滚动
当前 userInteracted 一旦为 true 永久停止;如需重置,可新增重置方法:
typescript
运行
const resetAutoScroll = () => {
userInteracted = false
handleScroll()
}
代码如下:
let scrollInterval: number | null = null; let userInteracted = false; const stopScroll = () => { userInteracted = true; if (scrollInterval !== null) { clearInterval(scrollInterval); scrollInterval = null; } }; const handleScroll = () => { if (userInteracted || !scTop.value) return; // Start from the current scroll position let startPosition = scTop.value.scrollTop; let endPosition = scTop.value.scrollHeight - scTop.value.clientHeight; let h = 1; scrollInterval = window.setInterval(() => { if (userInteracted || h > 1000) { if (scrollInterval !== null) { clearInterval(scrollInterval); scrollInterval = null; } return; } nextTick(() => { if (scTop.value) { scTop.value.scrollTop = startPosition + h * 3; } }); h++; }, 10); // Adjust the interval time for smoother or faster scrolling };