跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

uni-app怎么做数字增长滚动特效 uni-app大屏数据动效实现【代码】

最稳方案是用countUp.js,需$nextTick+createSelectorQuery确保节点挂载,小程序端须适配虚拟节点或改用轻量版;禁用v-for中重复实例化,复用实例调用update()。 uni-app里用
countUp.js
实现数字滚动增长最稳 直接上结论:别手写定时器+插值,
countUp.js
是目前 uni-app 大屏项目中数字动效兼容性最好、体积最小、可配置性最强的方案。它不依赖 Vue 响应式重绘,纯 CSS + requestAnimationFrame 驱动,H5、小程序(需基础库 2.24+)、App 端都跑得动。 常见错误是直接在
onLoad
里调用
new CountUp(...)
,但 uni-app 的生命周期和 DOM 渲染时机不一致,容易报
target is null
错误。 必须等节点挂载完成再初始化,推荐用
$nextTick
+
uni.createSelectorQuery()
查找真实 DOM 节点 小程序端不能传入原生 DOM 元素,得用
fields({ node: true })
拿到
node
对象再转成可操作元素 避免在
v-for
中每个 item 都 new 一个实例,复用
CountUp
实例并调用
update()
更省资源 uni-app 小程序端
countUp
报错
Cannot read property 'style' of null
这是最常卡住人的点:小程序里
querySelector
返回的是虚拟节点对象,不是浏览器 DOM,直接传给
CountUp
会炸。 正确做法是先确保节点已渲染,再用
createSelectorQuery
提取真实可操作节点:
// 示例:绑定 ref="numEl" 的 view 元素 this.$nextTick(() => { const query = uni.createSelectorQuery().in(this); query.select('#numEl').fields({ node: true, size: true }, res => { if (res && res.node) { // 小程序需用 createCanvasContext 或 getBoundingClientRect 模拟?不,这里用 res.node 直接传 // 但 countUp.js 默认不认,所以得 patch:用 res.node.querySelector('text') 或用自定义渲染器 // 更简单方案:改用支持小程序的轻量版,比如 github.com/ustbhuangyi/countup-weapp(已适配) // 或降级为手动 requestAnimationFrame + innerText 更新(见下节) } }).exec(); });
uni-app 微信小程序基础库 node 字段,只能 fallback 到纯 JS 插值 +
setData
,但频次高会卡顿 H5 端可直接用原生
document.getElementById
,无需 query App 端(vue2/nvue)要用
uni.createSelectorQuery().select
,且必须加
.in(this)
不用第三方库,纯
requestAnimationFrame
手写数字滚动(适合简单场景) 如果就几个数字、不需要 easing、不追求像素级平滑,手写更可控,也避开了兼容性包袱。 核心逻辑就三步:记录起始值、目标值、总时长,每帧算当前值并更新
data
;注意防抖和重复触发:
startCount(to, duration = 2000) { const from = this.currentValue; const startTime = performance.now(); const animate = (timestamp) => { const elapsed = timestamp - startTime; const progress = Math.min(elapsed / duration, 1); // 缓动函数:easeOutCubic const easeProgress = 1 - Math.pow(1 - progress, 3); this.currentValue = Math.floor(from + (to - from) * easeProgress); if (progress < 1) { requestAnimationFrame(animate); } }; requestAnimationFrame(animate); }
别用
setTimeout
递归,精度差、易积压、无法被浏览器优化 每次调用前要清掉上一次动画(存 cancelId),否则多个动效叠加会疯掉 小程序里
requestAnimationFrame
在非 H5 平台可能未实现,得用
uni.getSystemInfoSync().platform === 'ios' ? ... : ...
分支兜底 大屏多数字同时滚动时 CPU 占用飙升怎么办 本质是动效节点太多 + 频繁
setData
/
innerHTML
更新。不是代码写得不够“炫”,而是没做节流和分帧。 把 20 个数字分成每批 3 个,用
setTimeout
错峰启动,间隔 80ms,肉眼无感,CPU 直降 40% 禁用过渡动画的数字(比如单位、图标)不要参与动效,只更新纯数值部分,减少重排 真机调试时发现 iOS 微信里
transform: scale()
+ 数字变化会触发全层重绘,换成
opacity
或
color
变化更稳 上线前务必关掉
console.log
和所有调试动画,某些低端安卓机连
console.time
都能拖慢帧率 动效不是越多越好,大屏上用户视线焦点有限,优先保证关键指标的准确性和节奏感,其余数字滚动只是辅助呼吸感——这点很容易被忽略,结果调了一周性能,最后发现关掉两个次要动效,帧率就回到 60fps 了。

相关文章