Skip to content

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执行间隔(毫秒),仅在循环模式下生效number0
isLoop是否开启循环模式booleanfalse

返回值

类型说明
() => 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❌ 不支持

相关文档

🎯 核心功能

🎨 样式相关

🔧 开发工具

📱 移动端优化

🎪 高级用法

基於Vant構建的企業級移動端解決方案