文章摘要
加载中...|
此内容根据文章生成,并经过人工审核,仅用于文章内容的解释与总结

使用defer优化白屏时间

原理:

  • requestAnimationFrame 每帧自增一个计数器(frameCount++)。
  • 当计数器达到你设定的帧数(maxCount)后,就停止递归调用。
  • 暴露一个 defer(n) 方法,直接看当前计数是否 ≥ n,来判断“延迟 n 帧”是否完成。
  • 组件销毁时用 cancelAnimationFrame 停掉循环,避免无用消耗。

vue3版本写法及使用

javascript
import { onMounted, ref } from "vue";

export function useDefer(maxCount = 60) {
  const frameCount = ref(0);

  let rafId;

  function updateFrameCount() {
    rafId = requestAnimationFrame(() => {
      frameCount.value += 1;
      if (frameCount.value >= maxCount) return;
    });
    updateFrameCount();
  }

  updateFrameCount();

  onMounted(() => {
    cancelAnimationFrame(rafId);
  });

  return function defer(n) {
    return frameCount.value >= n;
  };
}
html
<script setup>
  import { useDefer } from "@/utils/defer.js";
  const defer = useDefer();
</script>
<template>
  <div v-for="n in 100">
    <span v-if="defer(n)">{{n}}</span>
  </div>
</template>

vue2版本写法及使用

javascript
// src/mixins/defer.js
export default {
  props: {
    maxCount: {
      type: Number,
      default: 60,
    },
  },
  data() {
    return {
      frameCount: 0,
      rafId: null,
    };
  },
  created() {
    // 开始递归 RAF
    const tick = () => {
      this.rafId = requestAnimationFrame(() => {
        this.frameCount++;
        // 未达到上限才继续
        if (this.frameCount < this.maxCount) {
          tick();
        }
      });
    };
    tick();
  },
  beforeDestroy() {
    // 组件销毁前取消
    cancelAnimationFrame(this.rafId);
  },
  methods: {
    defer(n) {
      return this.frameCount >= n;
    },
  },
};
html
<script>
  import deferMixin from "@/mixins/defer";

  export default {
    name: "MyComponent",
    mixins: [deferMixin],
    // 如果需要修改默认 60 帧:
    props: {
      maxCount: {
        type: Number,
        default: 100,
      },
    },
  };
</script>
<template>
  <div v-for="n in 100">
    <span v-if="defer(n)">{{n}}</span>
  </div>
</template>
评论 隐私政策