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

前端项目的通用优化策略

一、虚拟滚动

当我们开发的时候,遇到大数据加载,页面卡顿的问题应该如何处理?大多数情况下,我们都是尽量通过分页的方式处理这类问题,但是总有一些特殊的情况我们必须把数据全部加载到前端进行处理。我曾经遇到过一个坑爹的组件,必须一次性加载几万条数据到页面上,导致一打开这个组件,就会让页面疯狂卡顿,当时便用了虚拟滚动解决了这个棘手的问题。

所以当我们遇到这种情况:渲染长列表的场景,当渲染条数过多时,所需要的渲染时间会很长,滚动时还会造成页面卡顿,整体体验非常不好。完全可以考虑使用虚拟滚动这个解决方案。

虚拟滚动——指的是只渲染可视区域的列表项,非可见区域的不渲染,在滚动时动态更新可视区域,该方案在优化大量数据渲染时效果是很明显的。以下这个图较为清晰地解释了虚拟滚动的工作原理。
在这里插入图片描述
虚拟滚动基本原理:

计算出 totalHeight 列表总高度,并在触发时滚动事件时根据 scrollTop 值不断更新 startIndex 以及 endIndex ,以此从列表数据 listData 中截取对应元素。

虚拟滚动插件

虚拟滚动的使用场景不少,网上有很多已经造好的轮子,我们也可以适当地选择更快更便捷的方式解决我们的页面问题。

虚拟滚动的插件有很多,比如 vue-virtual-scroller、vue-virtual-scroll-list、react-tiny-virtual-list、react-virtualized 等

这里简单介绍 vue-virtual-scroller 的使用

// 安装插件
npm install vue-virtual-scroller// main.js
import VueVirtualScroller from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'Vue.use(VueVirtualScroller)// 使用
<template> <RecycleScroller class="scroller" :items="list" :item-size="32" key-field="id" v-slot="{ item }"> <div class="user"> {{ item.name }} </div></RecycleScroller> 
</template>

该插件主要有 RecycleScroller.vue、DynamicScroller.vue 这两个组件,其中 RecycleScroller 需要 item 的高度为静态的,也就是列表每个 item 的高度都是一致的,而 DynamicScroller 可以兼容 item 的高度为动态的情况

二、Web Worker 优化长任务

浏览器对页面的渲染时单线程的,导致我们的页面无法同时渲染CSS和JS代码。所以由于浏览器 GUI 渲染线程与 JS 引擎线程是互斥的关系,当页面中有很多长任务时,会造成页面 UI 阻塞,出现界面卡顿、掉帧等情况。

如果直接把下面这段代码直接丢到主线程中,计算过程中页面一直处于卡死状态,无法操作。

let sum = 0;
for (let i = 0; i < 200000; i++) {for (let i = 0; i < 10000; i++) {sum += Math.random()}}

使用 Web Worker 执行上述代码时,计算过程中页面正常可操作、无卡顿

// worker.js
onmessage = function (e) {// onmessage获取传入的初始值let sum = e.data;for (let i = 0; i < 200000; i++) {for (let i = 0; i < 10000; i++) {sum += Math.random()}}// 将计算的结果传递出去postMessage(sum);
}

Web Worker 的通信时长

当然Web Worker我们也不能滥用,毕竟加载worker也是需要消耗一定的服务器资源。并不是执行时间超过 50ms 的任务,就可以使用 Web Worker,还要先考虑通信时长的问题假如一个运算执行时长为 100ms,但是通信时长为 300ms, 用了 Web Worker可能会更慢
比如新建一个 web worker, 浏览器会加载对应的 worker.js 资源,下图中的 Time 是这个资源的通信时长(也叫加载时长)。

当任务的运算时长 - 通信时长 > 50ms,推荐使用Web Worker

三、requestAnimationFrame 制作动画

页面如果想要更加吸人眼球,动画必不可少。但是动画有时候会让页面看起来卡顿,而且也比较消耗浏览器的资源。那么为了解决这样的一些问题,我们可以使用requestAnimationFrame这个API来处理我们的动画效果。

requestAnimationFrame 是浏览器专门为动画提供的 API,它的刷新频率与显示器的频率保持一致,使用该 api 可以解决用 setTimeout/setInterval 制作动画卡顿的情况。

①引擎层面
setTimeout/setInterval 属于 JS引擎,requestAnimationFrame 属于 GUI引擎JS引擎与GUI引擎是互斥的,也就是说 GUI 引擎在渲染时会阻塞 JS 引擎的计算。

②时间是否准确
requestAnimationFrame 刷新频率是固定且准确的,但 setTimeout/setInterval 是宏任务,根据事件轮询机制,其他任务会阻塞或延迟js任务的执行,会出现定时器不准的情况。

③性能层面
当页面被隐藏或最小化时,setTimeout/setInterval 定时器仍会在后台执行动画任务,而使用 requestAnimationFrame 当页面处于未激活的状态下,屏幕刷新任务会被系统暂停。

四、JS的加载方式

关于我们页面的加载,相信很多人都知道在单线程的加载方式下,很多时候错误的编码会导致页面的阻塞,从而影响用户的体验,那么关于这点,我们应该更详细地去了解JS的加载方式。

①正常模式

<script src="index.js"></script>

这种情况下 JS 会阻塞 dom 渲染,浏览器必须等待 index.js 加载和执行完成后才能去做其它事情。也就是说如果整个页面跑下来,遇到这行代码将会直接停止页面dom的渲染,等到js文件加载完毕后,才能够再去绘制页面。

②async 模式

<script async src="index.js"></script>

async 模式下,它的加载是异步的,JS 不会阻塞 DOM 的渲染,async 加载是无顺序的,当它加载结束,JS 会立即执行。

使用场景:若该 JS 资源与 DOM 元素没有依赖关系,也不会产生其他资源所需要的数据时,可以使用async 模式,比如埋点统计。

③defer 模式

<script defer src="index.js"></script>

defer 模式下,JS 的加载也是异步的,defer 资源会在 DOMContentLoaded 执行之前,并且 defer 是有顺序的加载。

如果有多个设置了 defer 的 script 标签存在,则会按照引入的前后顺序执行,即便是后面的 script 资源先返回。所以 defer 可以用来控制 JS 文件的执行顺序,比如 element-ui.js 和 vue.js,因为 element-ui.js 依赖于 vue,所以必须先引入 vue.js,再引入 element-ui.js。

defer 使用场景:一般情况下都可以使用 defer,特别是需要控制资源加载顺序时

④module 模式

<script type="module">import { a } from './a.js'</script>

在主流的现代浏览器中,script 标签的属性可以加上 type=“module”,浏览器会对其内部的 import 引用发起 HTTP 请求,获取模块内容。这时 script 的行为会像是 defer 一样,在后台下载,并且等待 DOM 解析。

Vite 就是利用浏览器支持原生的 es module 模块,开发时跳过打包的过程,提升编译效率。

⑤preload 模式

<link rel="preload" as="script" href="index.js">

link 标签的 preload 属性:用于提前加载一些需要的依赖,这些资源会优先加载。

1)preload 加载的资源是在浏览器渲染机制之前进行处理的,并且不会阻塞 onload 事件;

2)preload 加载的 JS 脚本其加载和执行的过程是分离的,即 preload 会预加载相应的脚本代码,待到需要时自行调用;

⑥prefetch 模式

<link rel="prefetch" as="script" href="index.js">

prefetch 是利用浏览器的空闲时间,加载页面将来可能用到的资源的一种机制;通常可以用于加载其他页面(非首页)所需要的资源,以便加快后续页面的打开速度。

prefetch 特点:

1)pretch 加载的资源可以获取非当前页面所需要的资源,并且将其放入缓存至少5分钟(无论资源是否可以缓存)

2)当页面跳转时,未完成的 prefetch 请求不会被中断

加载方式的总结

async、defer 是 script 标签的专属属性,对于网页中的其他资源,可以通过 link 的 preload、prefetch 属性来预加载。

如今现代框架已经将 preload、prefetch 添加到打包流程中了,通过灵活的配置,去使用这些预加载功能,同时我们也可以审时度势地向 script 标签添加 async、defer 属性去处理资源,这样可以显著提升性能。 所以通常情况下,当我们使用了打包工具时,也不需要我们去管理太多复杂的加载形式,只需要通过简单的配置即可达到我们想要的效果。

相关文章:

前端项目的通用优化策略

一、虚拟滚动 当我们开发的时候&#xff0c;遇到大数据加载&#xff0c;页面卡顿的问题应该如何处理&#xff1f;大多数情况下&#xff0c;我们都是尽量通过分页的方式处理这类问题&#xff0c;但是总有一些特殊的情况我们必须把数据全部加载到前端进行处理。我曾经遇到过一个…...

关于 IO、存储、硬盘和文件系统

关于IO、存储、硬盘和文件系统 0.引入1.了解IO1.1.存储器IO1.2.设备IO 2.存储介质和存储类型2.1.内存2.2.硬盘2.3.固态硬盘&#xff08;SSD&#xff09;2.4.U盘 3.硬盘的工作原理3.1.磁头3.2.盘片3.3.电动机3.4.硬盘的读写操作 4.文件系统概述4.1.文件系统的类型4.2.文件系统的…...

计算机网络期中复习提纲-酷酷的聪整理版

第一章 概述 1.请介绍计算机网络在逻辑上的组成及其各自的作用。 计算机网络在逻辑上可以分为终端子网和通信子网两部分。 终端子网是指连接计算机与网络的部分,主要负责将数据从计算机发送到通信子网,或将从通信子网接收到的数据传输到计算机。终端子网通常包括物理层和数据…...

clickhouse的嵌套数据结构Tuple、Array与Nested类型介绍和使用示例

文章目录 Tuple类型Array类型Nested类型使用示例单独使用Tuple数组嵌套 Array(Tuple)Nested类型 生产使用&#xff1a;分组查询 Tuple类型 Tuple是ClickHouse数据库中的一种数据类型&#xff0c;它允许在一个字段中存储由不同数据类型组成的元组(tuple)。元组可以包含任意数量…...

人脸修复增强调研

Real-ESRGAN 工程地址&#xff1a;https://github.com/xinntao/Real-ESRGAN 效果&#xff1a; 人脸增强部分&#xff0c;调用的GFPGAN. GFPGAN 工程地址&#xff1a;https://github.com/TencentARC/GFPGAN 论文效果&#xff1a; BasicSR-ESRGAN&#xff1a; 项目地址&a…...

【Java】继承和多态

文章目录 一、继承1.继承的例子&#xff08;is-a&#xff09;2.组合的例子&#xff08;has-a&#xff09; 二、多态1.重写2.重载 三、继承的语法四、继承的注意事项1.初始化的顺序&#xff1a;2.super关键字 五、继承访问限定符六、多态实现方式七、多态的理解注意事项&#xf…...

ThingsBoard集群部署之k8s

1、概述 今天终于有时间去搞这个啦,拖了很久了,一直没时间,因为我本地没有那么多机器资源,开虚拟机不够,如果租用阿里云服务器,需要有充值的时间,因为这个费用是按小时付费,需要有连贯的时间来搞才行,今天恰好有时间,就开始搞了,弄成功搞出来了,特地写博客记录下来…...

【Gorm】如何在 GORM 中实现模型之间的关联?

文章目录 关联1、Belongs To&#xff08;属于&#xff09;2、Has One&#xff08;拥有一个&#xff09;3、Has Many&#xff08;拥有多个&#xff09;4、Many To Many&#xff08;多对多&#xff09; 关联 ​ 当涉及到 ORM&#xff08;Object-Relational Mapping&#xff09;的…...

Linux危险命令

rm -rf 命令 该命令可能导致不可恢复的系统崩坏。 rm -rf / #强制删除根目录下所有东西。rm -rf * #强制删除当前目录的所有文件。rm -rf . #强制删除当前文件夹及其子文件夹。fork 炸弹 :() { :|:& };:不太好理解可以转换成 bomb() {bomb|bomb& }; bomb一旦执行…...

FPGA入门系列13--异步串口通信

文章简介 本系列文章主要针对FPGA初学者编写&#xff0c;包括FPGA的模块书写、基础语法、状态机、RAM、UART、SPI、VGA、以及功能验证等。将每一个知识点作为一个章节进行讲解&#xff0c;旨在更快速的提升初学者在FPGA开发方面的能力&#xff0c;每一个章节中都有针对性的代码…...

k8s基础4——deployment控制器、应用部署、升级、回滚、水平扩容缩容

文章目录 一、基本介绍二、应用程序生命周期2.1 部署应用2.2 应用升级2.2.1 修改YAML文件升级&#xff08;交互式&#xff09;2.2.2 命令指定镜像版本升级&#xff08;免交互式&#xff09;2.2.3 调用vim升级 2.3 滚动升级2.3.1 升级流程 2.4 应用回滚2.4.1 查看历史发布版本2.…...

动态规划算法——40道leetcode实例入门到熟练

目录 t0.解题五部曲1.基础入门题目1.509. 斐波那契数2.70. 爬楼梯3.746. 使用最小花费爬楼梯4.62. 不同路径5.63. 不同路径 II6.343. 整数拆分7.96. 不同的二叉搜索树 2.背包问题1.01背包&#xff08;二维数组实现&#xff09;2.01背包&#xff08;滚动数组实现&#xff09;1.4…...

Nmap入门到高级【第十一章】

预计更新第一章. Python 简介 Python 简介和历史Python 特点和优势安装 Python 第二章. 变量和数据类型 变量和标识符基本数据类型&#xff1a;数字、字符串、布尔值等字符串操作列表、元组和字典 第三章. 控制语句和函数 分支结构&#xff1a;if/else 语句循环结构&#…...

配置本地Angular环境并使用VsCode调试Angular前端项目

配置本地Angular环境并使用VsCode调试Angular前端项目 配置本地Angular环境部署Node.Js本地环境配置一下环境变量 使用vscode调试Angular安装vscode 配置本地Angular环境 部署Node.Js本地环境 1 从官网下载node.js, 本文为(v16.13.0) 下载地址: https://nodejs.org/dist/v16.…...

100ASK_全志V853-PRO开发板支持人形检测和人脸识别

1.前言 V853 芯片内置一颗 NPU核&#xff0c;其处理性能为最大 1 TOPS 并有 128KB 内部高速缓存用于高速数据交换&#xff0c;支持 OpenCL、OpenVX、android NN 与 ONNX 的 API 调用&#xff0c;同时也支持导入大量常用的深度学习模型。本章提供一个例程&#xff0c;展示如何使…...

简单实现基于UDP与TCP的回显服务器

目录 前言UDP 版的回显服务器需要用到的 api服务端客户端UDP 版本的字典客户端和字典服务器 TCP 版的回显服务器需要用到的 api服务器客户端对服务器进行改进(使用线程池)TCP 版本的字典客户端和字典服务器 前言 我们写网络程序, 主要编写的是应用层代码. 真正要发送这个数据,…...

家用洗地机有什么推荐的吗?家用洗地机哪款好

洗地机是创新、高效的清洁工具&#xff0c;其具有高性能的清洁能力和卓越的操作体验。与传统的清洁工具相比&#xff0c;洗地机可以迅速而彻底地打扫地面&#xff0c;降低清洁时间和人力成本&#xff0c;让我们在工作之余不用花费大量的时间和精力去打扫卫生&#xff0c;下面就…...

深度学习与文本聚类:一篇全面的介绍与实践指南

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…...

AP5153 线性降压恒流驱动芯片 2.5A

AP5153 是一种 PWM 调光的、低压 差的 LED 线性降压恒流驱动器。 AP5153 仅需要外接一个电阻和一个 NMOS 管就可以构成一个完整的 LED 恒 流驱动电路&#xff0c; 调节该外接电阻就可以调节 输出电流&#xff0c;输出电流可调范围为 20mA 到 3.0A。 AP5153 还可以通过在 DIM…...

Unity物理系统脚本编程(下)

一、修改物理材质 Unity对物体表面材料的性质做了件化处理&#xff0c;仅有5种常用属性&#xff1a; Dynamic Friction&#xff08;动态摩擦系数&#xff09;Static Friction&#xff08;静态摩擦系数&#xff09;Bounciness&#xff08;弹性系数&#xff09;Friction Combine…...

可靠性+灵活性:电力载波技术在楼宇自控中的核心价值

可靠性灵活性&#xff1a;电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中&#xff0c;电力载波技术&#xff08;PLC&#xff09;凭借其独特的优势&#xff0c;正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据&#xff0c;无需额外布…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

[ACTF2020 新生赛]Include 1(php://filter伪协议)

题目 做法 启动靶机&#xff0c;点进去 点进去 查看URL&#xff0c;有 ?fileflag.php说明存在文件包含&#xff0c;原理是php://filter 协议 当它与包含函数结合时&#xff0c;php://filter流会被当作php文件执行。 用php://filter加编码&#xff0c;能让PHP把文件内容…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...

深入解析 ReentrantLock:原理、公平锁与非公平锁的较量

ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...