useRaf 🎬
介绍
想要让你的动画丝滑如德芙?想要在浏览器重绘时机精准执行代码?useRaf 就是你的最佳拍档!🎯
这个 Hook 为你提供了便捷的 requestAnimationFrame 调用和取消功能,让你轻松掌控动画节奏,告别卡顿烦恼!
代码演示
基础用法 ⚡
在下一次浏览器重绘前执行代码,完美契合浏览器的渲染节奏:
js
import { useRaf } from '@vant/use';
export default {
setup() {
let count = 0;
// 在下一帧执行,只执行一次
useRaf(() => {
console.log(`第 ${++count} 次执行`); // 只会执行 1 次
console.log('🎬 动画开始!');
});
},
};循环动画 🔄
开启循环模式,创建连续的动画效果:
js
import { useRaf } from '@vant/use';
export default {
setup() {
let count = 0;
const cancelRaf = useRaf(
() => {
console.log(`🎭 第 ${++count} 帧`);
// 执行 5 次后停止
if (count === 5) {
console.log('🎬 动画结束!');
cancelRaf();
}
},
{
isLoop: true, // 开启循环模式
interval: 100, // 每 100ms 执行一次
},
);
},
};元素动画控制 🎨
结合 DOM 操作,创建流畅的元素动画:
js
import { ref } from 'vue';
import { useRaf } from '@vant/use';
export default {
setup() {
const elementRef = ref();
let position = 0;
const startAnimation = () => {
const cancelRaf = useRaf(
() => {
position += 2;
if (elementRef.value) {
elementRef.value.style.transform = `translateX(${position}px)`;
}
// 移动到 200px 时停止
if (position >= 200) {
console.log('🎯 动画完成!');
cancelRaf();
}
},
{
isLoop: true,
},
);
};
return {
elementRef,
startAnimation,
};
},
};性能监控 📊
利用 RAF 监控页面性能:
js
import { useRaf } from '@vant/use';
export default {
setup() {
let frameCount = 0;
let lastTime = performance.now();
const cancelRaf = useRaf(
() => {
frameCount++;
const currentTime = performance.now();
// 每秒计算一次 FPS
if (currentTime - lastTime >= 1000) {
const fps = Math.round((frameCount * 1000) / (currentTime - lastTime));
console.log(`📊 当前 FPS: ${fps}`);
frameCount = 0;
lastTime = currentTime;
}
},
{
isLoop: true,
},
);
// 10 秒后停止监控
setTimeout(() => {
cancelRaf();
console.log('📊 性能监控结束');
}, 10000);
},
};响应式动画 📱
根据设备性能调整动画频率:
js
import { useRaf } from '@vant/use';
export default {
setup() {
// 检测设备性能
const isLowPerformance = navigator.hardwareConcurrency <= 2;
const animationInterval = isLowPerformance ? 32 : 16; // 低性能设备降低帧率
let rotation = 0;
const elementRef = ref();
const startRotation = () => {
const cancelRaf = useRaf(
() => {
rotation += isLowPerformance ? 2 : 4; // 低性能设备减慢动画
if (elementRef.value) {
elementRef.value.style.transform = `rotate(${rotation}deg)`;
}
if (rotation >= 360) {
rotation = 0;
}
},
{
isLoop: true,
interval: animationInterval,
},
);
return cancelRaf;
};
return {
elementRef,
startRotation,
};
},
};API 参考
类型定义
ts
function useRaf(
callback: () => void,
options?: {
interval?: number;
isLoop?: boolean;
},
): () => void;参数说明
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| callback | 要执行的回调函数 | () => void | - |
| options | 配置选项 | RafOptions | {} |
RafOptions
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| interval | 执行间隔(毫秒),仅在循环模式下生效 | number | 0 |
| isLoop | 是否开启循环模式 | boolean | false |
返回值
| 类型 | 说明 |
|---|---|
() => void | 取消函数,调用后停止动画循环 |
实际应用场景
🎮 游戏开发
- 游戏循环渲染
- 角色移动动画
- 粒子效果系统
🎨 UI 动画
- 页面过渡效果
- 加载动画
- 滚动视差效果
📊 数据可视化
- 图表动画更新
- 实时数据展示
- 进度条动画
🔧 性能优化
- 批量 DOM 更新
- 防抖动画处理
- 性能监控工具
最佳实践
✅ 推荐做法
js
// 1. 及时清理动画
const cancelRaf = useRaf(callback, { isLoop: true });
onUnmounted(() => {
cancelRaf();
});
// 2. 根据设备性能调整
const interval = navigator.hardwareConcurrency <= 2 ? 32 : 16;
// 3. 避免在回调中进行复杂计算
useRaf(() => {
// 简单的 DOM 操作
element.style.transform = `translateX(${position}px)`;
});❌ 避免做法
js
// 1. 忘记清理循环动画
useRaf(callback, { isLoop: true }); // 可能导致内存泄漏
// 2. 在回调中进行复杂计算
useRaf(() => {
// 避免复杂计算,会影响性能
const result = heavyCalculation();
});
// 3. 过度使用循环模式
useRaf(callback, { isLoop: true, interval: 1 }); // 过高频率调试技巧
🔍 性能分析
js
// 监控动画性能
let frameTime = 0;
const cancelRaf = useRaf(() => {
const start = performance.now();
// 你的动画代码
animateElement();
frameTime = performance.now() - start;
if (frameTime > 16) {
console.warn(`⚠️ 动画帧耗时过长: ${frameTime.toFixed(2)}ms`);
}
}, { isLoop: true });🐛 调试工具
js
// 添加调试信息
const debugRaf = (callback, options) => {
console.log('🎬 RAF 动画开始', options);
return useRaf(() => {
console.log('📽️ 执行动画帧');
callback();
}, options);
};浏览器兼容性
| 浏览器 | 版本支持 |
|---|---|
| Chrome | ✅ 10+ |
| Firefox | ✅ 4+ |
| Safari | ✅ 6+ |
| Edge | ✅ 12+ |
| IE | ❌ 不支持 |
相关文档
🎯 核心功能
- useEventListener - 事件监听管理 - 事件处理的最佳伴侣
- usePageVisibility - 页面可见性 - 控制动画的播放暂停
- useWindowSize - 窗口尺寸 - 响应式动画必备
🎨 样式相关
- 主题定制 - Theme - 打造个性化动画主题
- Watermark - 水印组件 - 动态水印效果
🔧 开发工具
- Vant Use 介绍 - 了解更多组合式 API
- useToggle - 状态切换 - 动画状态管理
📱 移动端优化
- useRect - 元素位置 - 精确的动画定位
- useScrollParent - 滚动容器 - 滚动动画优化
🎪 高级用法
- useRelation - 组件关联 - 复杂动画编排
- useCustomFieldValue - 自定义字段 - 动画数据绑定