当前位置: 首页 > article >正文

利用 Vue 组合式 API 与 requestAnimationFrame 优化大量元素渲染

在 Vue 项目开发中,当面临需要渲染大量元素的场景时,如何高效地处理渲染过程以避免性能瓶颈是一个关键问题。本文将深入探讨一种基于 Vue 3 的 <script setup> 语法糖和 requestAnimationFrame 的解决方案,通过自定义 useDefer 组合式函数来逐步渲染大量元素,提升页面性能与用户体验。

一、问题引入

在前端开发中,直接渲染大量元素可能会导致页面卡顿甚至无响应。例如,当我们需要在页面上展示 10000 个数据项时,如果一次性将所有元素都渲染到页面上,浏览器需要处理大量的 DOM 操作,这对于性能来说是一个巨大的挑战。用户可能会看到长时间的白屏或者页面滚动不流畅等问题,严重影响了用户体验。

二、useDefer 组合式函数解析

1. 函数定义与基本变量

import {onUnmounted, ref} from "vue";

export function useDefer(maxCount = 100) {
    const frameCount = ref(0);
    let rafId;

这里首先从 Vue 中引入了 onUnmountedrefref 用于创建一个响应式数据,frameCount 就是一个响应式的变量,用于记录当前已经经过的动画帧数。rafId 则用于存储 requestAnimationFrame 返回的 ID,以便后续在组件卸载时能够取消动画帧的请求。

2. updateFrameCount 函数 - 动画帧更新逻辑

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

updateFrameCount 函数是整个逻辑的核心部分。它使用 requestAnimationFrame 来创建一个动画帧的循环。在每一帧中,首先将 frameCount 的值加 1,表示已经经过了一个新的动画帧。然后检查 frameCount 是否已经达到了预设的 maxCount。如果没有达到,就继续递归调用 updateFrameCount,这样就形成了一个持续运行的动画帧更新循环,直到达到 maxCount 为止。

3. 组件卸载时的清理工作

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

当组件卸载时,使用 onUnmounted 钩子函数来取消之前通过 requestAnimationFrame 创建的动画帧请求。这是非常重要的一步,避免了在组件已经不需要更新时仍然占用浏览器资源,防止内存泄漏等问题。

4. defer 函数 - 元素渲染控制

return function defer(n) {
    return frameCount.value >= n;
}

最后返回的 defer 函数接受一个参数 n,它会根据当前的 frameCount 值与传入的 n 进行比较。如果 frameCount 的值大于等于 n,则表示当前元素可以进行渲染,返回 true;否则返回 false。这样就可以在模板中根据元素的索引来控制元素的渲染时机,实现逐步渲染的效果。

三、组件中的使用

在 Vue 组件中,使用 useDefer 组合式函数非常简单:

<script setup>
import {useDefer} from '@/hooks/useDefer'
const defer = useDefer()
</script>

<template>
  <div v-for="(item,index) in 10000">
    <div class="box" v-if="defer(index)">
      {{ item }}
    </div>
  </div>
</template>

通过引入 useDefer 函数并获取 defer 实例,在模板的 v-for 循环中,使用 v-if 指令结合 defer 函数来根据元素的索引控制每个 div 元素的渲染时机。这样,不是一次性渲染所有 10000 个元素,而是按照 requestAnimationFrame 设定的帧率逐步渲染,减轻了浏览器的负担,提高了页面的响应速度和流畅度。

四、总结与优化思考

通过自定义的 useDefer 组合式函数,我们有效地解决了大量元素渲染时可能出现的性能问题。这种方式利用了 requestAnimationFrame 与 Vue 的组合式 API 的优势,实现了元素的逐步渲染。然而,在实际应用中,还可以进一步优化。例如,可以根据页面的可见区域动态调整 maxCount 的值,只渲染当前可见区域附近的元素,对于不可见区域的元素延迟渲染甚至不渲染,进一步提高性能。同时,也可以考虑添加更多的参数来灵活控制渲染策略,以适应不同的业务场景和性能需求。希望本文能够为 Vue 开发者在处理大量元素渲染问题时提供一种有效的思路和解决方案,让我们能够构建出更加高效、流畅的 Vue 应用程序。

五、整体JS代码

import {onUnmounted, ref} from "vue";

export function useDefer(maxCount = 100) {
    const frameCount = ref(0);
    let rafId;
    function updateFrameCount() {
        rafId = requestAnimationFrame(() => {
            frameCount.value++;
            if (frameCount.value >= maxCount) {
                return;
            }
            updateFrameCount();
        });
    }

    updateFrameCount();
    onUnmounted(()=>{
        cancelAnimationFrame(rafId);
    })
    return function defer(n) {
        return frameCount.value >= n;
    }
}

http://www.kler.cn/a/411304.html

相关文章:

  • 对比C++,Rust在内存安全上做的努力
  • uniapp前端开发,基于vue3,element plus组件库,以及axios通讯
  • Pytorch使用手册-快速开始(专题一)
  • 常用Rust日志处理工具教程
  • 【数据结构与算法】合并链表、链表分割、链表回文结构
  • 加菲工具 - 好用免费的在线工具集合
  • Paddle Inference部署推理(一)
  • QT-installEventFilter
  • GaussDB高智能--库内AI引擎:模型管理数据集管理
  • 蓝桥杯c++算法秒杀【6】之动态规划【下】(数字三角形、砝码称重(背包问题)、括号序列、异或三角:::非常典型的必刷例题!!!)
  • 前端 Vue 3 后端 Node.js 和Express 结合cursor常见提示词结构
  • C语言解析命令行参数
  • xiaolin coding 图解网络笔记——TCP篇
  • 2686694 - 操作方法:MSEG - DBSQL_REDIRECT_INCONSISTENCY
  • 道路机器人识别交通灯,马路,左右转,黄线,人行道,机器人等路面导航标志识别-使用YOLO标记
  • Python毕业设计选题:基于django+vue的期货交易模拟系统的设计与实现
  • PyTorch3
  • SD-WAN加速是怎么实现的?
  • MODBUS规约的秘密之五-----如何用C++编写MODBUS规约
  • 基于物联网技术的智能家居安全监控体系构建
  • 利用HTML5和CSS来实现一个漂亮的表格样式
  • Spring Boot——统一功能处理
  • Rust学习笔记_01——基础
  • 新能源汽车充电插口类型识别-YOLO标记,可识别Type1,ccs2的充电标准
  • 【机器学习】如何使用Python的Scikit-learn库实现机器学习模型,并对数据进行预处理和特征缩放以提高模型性能?
  • 【青牛科技】D1117 1.0A低压差线性稳压电路芯片介绍,可保证了输出电压精度控制在±1.5%的范围内