前端优化:从Vue/React/Svelte的数组更新->渲染策略剖析数组大列表数据展示优化策略

在现代前端框架中,数组的渲染是一个重要的功能。不同的框架在处理数组的操作(如新增、删除和更新)时有不同的实现方式和优化手段。本文将对比 Vue、React 和 Svelte 在数组渲染方面的特点,并讨论其优缺点,特别是与直接操作 DOM 的差异,以及 Web Components 的实现方式和优势。

这几个方式分别使用了vdom,dom操作以及手动控制,先送出个结论:全量更新上框架、增量更新dom操作、减少每帧计算量

Vue 的数组渲染

在 Vue 中,数组的渲染通常使用 v-for 指令。Vue 依靠响应式系统来追踪数据的变化,并根据具体的变化(新增、删除或更新)重新渲染相关 DOM 节点。Vue 的响应式系统使开发变得简单且易维护,因为框架会自动管理数据的变化并更新 DOM。

示例代码:

const app = Vue.createApp({data() {return {items: [{ id: 1, name: 'Item 1' },{ id: 2, name: 'Item 2' },]};},methods: {addItem() {this.items.push({ id: this.items.length + 1, name: `Item ${this.items.length + 1}` });}}
});app.component('item-list', {template: `<ul><li v-for="(item, index) in items" :key="item.id">{{ item.name }}</li></ul><button @click="addItem">Add Item</button>`,props: ['items'],methods: {addItem() {this.$emit('add-item');}}
});app.mount('#app');

数组操作:

  • 新增:使用 push 方法时,Vue 通过数据绑定系统自动侦测到数组变化并更新 DOM。
  • 删除:使用 splicepop,同样会触发响应式更新。
  • 更新:可以直接修改数组项,Vue 也会追踪并自动更新视图。

组件更新流程:

数据变化
触发响应式追踪
比较新旧数据
生成新虚拟 DOM
虚拟 DOM 对比
更新实际 DOM

优缺点:

  • 优点:Vue 的响应式系统使得开发者可以简单地操作数组,框架会自动更新 DOM,减少了手动维护的复杂性,确保了数据与视图的同步。
  • 缺点:对于大规模数据的频繁操作,Vue 可能会有性能瓶颈,因为它需要对数组的每个变化进行追踪,这可能导致不必要的开销,尤其是在大规模复杂项目中。

React 的数组渲染

React 通过 map() 方法来渲染数组,并依赖于组件的 state 来管理变化。React 需要手动管理数组的变化并调用 setState 来触发重新渲染。在 React 中,每次状态变化都会触发虚拟 DOM 的更新,并通过 diffing 算法来找出变化的部分,最终更新实际 DOM。

示例代码:

import React, { useState } from 'react';function ItemList() {const [items, setItems] = useState([{ id: 1, name: 'Item 1' },{ id: 2, name: 'Item 2' }]);const addItem = () => {setItems([...items, { id: items.length + 1, name: `Item ${items.length + 1}` }]);};return (<div><ul>{items.map(item => (<li key={item.id}>{item.name}</li>))}</ul><button onClick={addItem}>Add Item</button></div>);
}export default ItemList;

数组操作:

  • 新增:使用 setItems([...items, newItem]) 更新 state,React 根据 diffing 算法对比新旧虚拟 DOM,找出变化并更新实际 DOM。
  • 删除:通过过滤数组并调用 setState,触发重新渲染。
  • 更新:直接修改数组项不会更新视图,必须使用 setState 来触发重新渲染。

组件更新流程:

调用 setState
生成新状态
创建新虚拟 DOM
虚拟 DOM 对比
更新实际 DOM

优缺点:

  • 优点:React 的 diffing 算法可以有效减少 DOM 的直接操作,确保最小化更新,提升性能,避免了手动操作 DOM 所带来的复杂性。
  • 缺点:需要使用不可变数据来更新 state,开发者必须显式地管理数组状态,相对而言代码可能更加繁琐,特别是对于大型数组的频繁操作,代码可读性和维护性会受到影响。

Svelte 的数组渲染

Svelte 通过编译时的优化来追踪状态变化,在数组操作方面更加直观和高效。Svelte 不需要手动调用类似 setState 的方法,变量的赋值变化即可触发视图更新。Svelte 的设计理念是编译时而非运行时更新,这使得它在性能上更加优越。

示例代码:

<script>let items = [{ id: 1, name: 'Item 1' },{ id: 2, name: 'Item 2' }];function addItem() {items = [...items, { id: items.length + 1, name: `Item ${items.length + 1}` }];}
</script><ul>{#each items as item (item.id)}<li>{item.name}</li>{/each}
</ul><button on:click={addItem}>Add Item</button>

数组操作:

  • 新增:直接修改数组即可,Svelte 会自动追踪赋值操作并更新 DOM。
  • 删除:通过重新赋值给数组,Svelte 会自动处理重新渲染。
  • 更新:直接修改数组项也会触发更新,无需额外的方法调用。

组件更新流程:

数据变化
编译生成新代码
更新实际 DOM

优缺点:

  • 优点:Svelte 的编译时优化使得它在数组操作上显得非常轻量且高效。开发者不需要担心如何触发渲染,代码更加直观。编译时的响应式机制也大大减少了运行时的开销。
  • 缺点:Svelte 的响应式机制依赖于编译时,虽然性能极好,但对于复杂状态管理可能需要更多的考虑,对于动态性较强的应用可能存在一定的局限性。

与手动 DOM 操作的对比

手动操作 DOM 时,开发者需要显式地操作节点,例如使用 document.createElementappendChildremoveChild。这不仅代码量大,且易出错,尤其是在处理复杂的数组变化时,维护节点状态可能导致非常混乱的代码。现代框架通过抽象这些底层的操作,使开发者能够更加专注于业务逻辑,而不是 DOM 的管理。

优缺点对比:

  • Vue/React/Svelte 优点

    • 自动化状态跟踪与渲染,极大减少了手动 DOM 操作的复杂度。
    • 高效的更新机制(如 React 的 diffing 算法和 Svelte 的编译时优化)可以确保性能,避免了不必要的 DOM 重绘。
    • 提高代码可读性和可维护性,尤其是在大型项目中,减少了开发和维护中的出错几率。
  • 手动 DOM 操作的缺点

    • 容易产生不一致性,手动管理节点的增删改需要开发者自己追踪变化,容易遗漏,导致数据与视图不一致。
    • 难以维护,特别是当数据复杂时,手动更新 DOM 需要大量的代码,代码复杂度随着应用规模的增长而增加。
    • 无法享受现代框架的优化,性能较差,手动管理大量 DOM 节点操作会导致性能瓶颈。

DOM 操作与 Web Component

Web Components 是一种基于浏览器原生 API 的技术,可以创建自定义、可重用的 HTML 元素。通过使用 Shadow DOM、HTML Templates 和自定义元素,Web Components 可以实现封装和模块化开发。与现代框架相比,Web Components 提供了一种更加原生的方法来实现组件化开发,适合用于跨框架的组件共享和通用组件的封装。

示例代码:

<template id="item-list"><ul></ul><button>Add Item</button>
</template><script>class ItemList extends HTMLElement {constructor() {super();const template = document.getElementById('item-list').content;this.attachShadow({ mode: 'open' }).appendChild(template.cloneNode(true));this.items = [{ id: 1, name: 'Item 1' },{ id: 2, name: 'Item 2' }];this.render();this.shadowRoot.querySelector('button').addEventListener('click', () => this.addItem());}render() {const ul = this.shadowRoot.querySelector('ul');ul.innerHTML = '';this.items.forEach(item => {const li = document.createElement('li');li.textContent = item.name;ul.appendChild(li);});}addItem() {this.items.push({ id: this.items.length + 1, name: `Item ${this.items.length + 1}` });this.render();}}customElements.define('item-list', ItemList);
</script><item-list></item-list>

数组操作:

  • 新增:通过 addItem() 方法新增数组项,并调用 render() 方法更新 DOM。
  • 删除:可以手动从数组中删除项,并调用 render() 方法更新 DOM,确保数据和视图保持同步。
  • 更新:修改数组项后需显式调用 render() 方法重新渲染,保持数据与视图一致。

组件更新流程:

事件触发
修改数据
调用 render 方法
更新实际 DOM

优缺点:

  • 优点

    • 原生支持,Web Components 是浏览器提供的标准,无需依赖第三方框架,具有广泛的兼容性。
    • 强封装性,通过 Shadow DOM 隔离样式和功能,避免与页面其他部分的冲突,确保组件的独立性。
    • 可重用性,适合创建跨项目的可复用 UI 组件,尤其是适用于需要跨多个框架使用的场景。
  • 缺点

    • 开发复杂度较高,需要手动管理状态和 DOM 更新,与现代框架相比缺乏自动化的状态跟踪和高效的渲染机制。
    • 缺少像 Vue、React、Svelte 这样的高级状态管理和优化机制,开发者需要自己处理复杂的逻辑。
    • 对于复杂交互和大型应用,手动管理状态和 DOM 更新可能不如现代前端框架高效,代码的可读性和维护性也会降低。

数组更新的优化策略

在处理数组更新时,使用适当的优化策略可以显著提高性能,特别是对于大型数组和频繁的更新操作。以下是几种常见的优化策略:

1. Key 的使用

在 Vue 和 React 中,为数组中的每个项分配唯一的 key 可以帮助框架识别哪些项发生了变化。合理使用 key 可以减少不必要的 DOM 更新。

2. 分片渲染(Chunk Rendering)

对于大型列表,使用分片渲染(将大列表拆分为多个小片段并逐步渲染)可以减少一次性渲染的开销,提升页面响应速度。这种方式适用于需要显示大量数据的场景。

3. 虚拟滚动(Virtual Scrolling)

虚拟滚动是一种仅渲染可视区域的数据项的方法,可以极大地减少 DOM 中同时存在的节点数量,从而提升性能。适用于需要渲染大量数据项的长列表。

4. 不可变数据结构

在 React 中,使用不可变数据结构可以确保状态更新时产生新的引用,从而帮助框架快速检测变化并触发重新渲染。这也是 React 中推荐的最佳实践。

5. 使用节流和防抖

对于频繁的数组操作,可以使用节流(throttle)或防抖(debounce)技术来减少函数的调用次数,避免过于频繁地触发重新渲染,提升性能。

6. 批量更新

在某些场景下,可以将多个数组操作合并为一次批量更新。例如,在 React 中,可以利用批处理(batching)机制将多个 setState 调用合并为一次 DOM 更新,从而减少不必要的重复渲染。

7. 优化 diff 算法

对于框架内部的优化,可以通过调整 diff 算法的策略,例如在 Vue 中使用 v-once 指令避免不变数据的重复比较,或者在 React 中通过 shouldComponentUpdate 方法控制组件的重新渲染。

数组更新优化对比表

优化策略VueReactSvelteWeb Components
Key 的使用必须,确保高效 diff必须,确保高效 diff可选(通过编译优化)无需使用
分片渲染通过第三方库支持通过第三方库支持通过第三方库支持需要手动实现
虚拟滚动通过第三方库支持通过第三方库支持通过第三方库支持需要手动实现
不可变数据结构可选推荐无需,自动追踪需要手动管理
节流与防抖可通过工具函数实现可通过工具函数实现可通过工具函数实现需要手动实现
批量更新自动处理自动处理自动处理无自动支持
优化 diff 算法内建内建编译时优化无内建 diff 优化

总结

Vue、React 和 Svelte 各有优势:Vue 的响应式系统简化开发,React 利用虚拟 DOM 提供高效更新,Svelte 通过编译时优化提升性能,Web Components 则提供原生封装与复用。选择框架取决于项目复杂度和性能需求。

对于简单项目,Web Components 提供高可复用性;而在大型应用中,Vue、React 和 Svelte 的状态管理和优化策略更适合提升开发效率。

最近有点心乱,打算离职专门做开放项目,偶尔断更 - -!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/882543.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】STL——priority_queue优先级队列

目录 前言priority_queue的使用简单使用在OJ中的使用 priority_queue的模拟实现基本功能仿函数在这里插入图片描述 前言 上一节我们说了stack和queue这两种容器适配器&#xff0c;而priority_queue&#xff08;优先级队列&#xff09;同样也是属于容器适配器&#xff0c;它会优…

使用Python在Jupyter Notebook中显示Markdown文本

使用Python在Jupyter Notebook中显示Markdown文本 引言1. 导入必要的模块2. 定义一个函数来显示Markdown文本3. 使用print_md函数显示Markdown文本4. 总结 引言 作为一名Python初级程序员&#xff0c;你可能已经熟悉了Jupyter Notebook这个强大的工具。Jupyter Notebook不仅支…

【Fargo】9:模拟图片采集的内存泄漏std::bad_alloc

std::bad_alloc 崩溃。这样的内存分配会导致内存耗尽 is simulating an image of size 640x480 with 3 bytes per pixel, resulting in an allocation of approximately 921,600 bytes (or around 900 KB) for each image. The error you’re encountering (std::bad_alloc) ty…

Spring Boot中使用FlexyPool动态监控管理数据库连接池

在现代软件开发中&#xff0c;数据库连接管理是性能优化的关键一环。传统的固定大小连接池在面对突发流量或持续增长的数据访问需求时&#xff0c;往往显得力不从心。FlexyPool正是为了解决这一问题而诞生的创新解决方案。它不仅能够根据实际需求动态调整连接池大小&#xff0c…

【c++】左值右值

1. 普通类型的变量&#xff0c;因为有名字&#xff0c;可以取地址&#xff0c;都认为是左值。 2. const修饰的常量&#xff0c;不可修改&#xff0c;只读类型的&#xff0c;理论应该按照右值对待&#xff0c;但因为其可以取地址(如果只是const类型常量的定义&#xff0c;编译器…

Arduino 1.8 无法启动,闪屏过后,不出主界面

突然打不开了&#xff0c;闪屏过后&#xff0c;不出主界面&#xff0c;一直这样&#xff0c;任务栏有图标。 1. 使用调试版的arduino_debug.exe运行显示如下&#xff0c;也没有任何错误。 C:\Users\youuser>"C:\Program Files (x86)\Arduino\arduino_debug.exe"…

Java 多线程(四)—— 线程安全 与 volatile 与 单例模式

什么是线程安全 在进行多线程编程的时候&#xff0c;当我们编写出来的多线程的代码运行结果不符合我们的预期的时候&#xff0c;这时候就是 bug&#xff0c;这种 bug 是由于多线程的问题而产生出来的 bug 我们称之为 线程安全问题 当我们编写出来的多线程代码运行之后的结果符…

计算机毕业设计选题推荐【基础功能+创新点】【Java方向】

选以下是30个Java方向的精选毕设选题&#xff0c;每个选题包括基础功能和创新点&#xff0c;供你参考。 文末有作者名片喔&#xff0c;需要交流 (毕业) 可联系 在线教育平台 基础功能&#xff1a;用户注册与登录&#xff0c;课程浏览与搜索&#xff0c;课程购买与观看&#xf…

学习文档(5)

Redis应用 目录 Redis应用 Redis 除了做缓存&#xff0c;还能做什么&#xff1f; Redis 可以做消息队列么&#xff1f; Redis 可以做搜索引擎么&#xff1f; 如何基于 Redis 实现延时任务&#xff1f; Redis 除了做缓存&#xff0c;还能做什么&#xff1f; 分布式锁&…

WPF中的常见控件

控件模板ControlTemplate 在 WPF (Windows Presentation Foundation) 中&#xff0c;ControlTemplate 是一个 XAML 模板&#xff0c;它定义了控件的视觉结构和布局。通过使用 ControlTemplate&#xff0c;你可以自定义控件的外观&#xff0c;包括它的样式、颜色、形状以及包含…

三周精通FastAPI:5 查询参数和字符串校验

FastAPI手册&#xff1a;https://fastapi.tiangolo.com/zh/tutorial/query-params-str-validations/ 查询参数和字符串校验 FastAPI 允许你为参数声明额外的信息和校验。让我们以下面的应用程序为例&#xff1a; from fastapi import FastAPIapp FastAPI()app.get("/it…

基于springboot+thymeleaf+springsecurity搭建一套web小案例

一、前言 本案例中的源代码已上传到资源库&#xff0c;可自行下载&#xff0c;传送阵 https://download.csdn.net/download/qq_36260963/89906196 Spring Boot是为了简化Spring应用的创建、运行、调试、部署等而出现的&#xff0c;使用它可以做到专注于Spring应用的开发&#x…

git clone 鉴权失败

git clone 鉴权失败问题 1. 问题描述2. 解决方法 1. 问题描述 使用git clone自己的代码报如下错误&#xff1a; 正克隆到 xxx... Username for https://github.com: Password for https://xxxgithub.com: remote: Support for password authentication was removed on Augu…

RAG流程的实现与改进

一、 RAG流程图 数据入库&#xff1a;读取本地数据并切成小块&#xff0c;并把这些小块经过编码embedding后&#xff0c;存储在一个向量数据库中&#xff08;下图1——6步&#xff09;&#xff1b;相关性检索&#xff1a;用户提出问题&#xff0c;问题经过编码&#xff0c;再在…

Vue项目中实现拖拽上传附件:原生JS与Element UI组件方法对比

在现代化的Web应用中&#xff0c;文件上传是一个基本功能。随着技术的发展&#xff0c;拖拽上传已经成为提升用户体验的一个重要特性。在Vue项目中&#xff0c;我们可以通过原生JavaScript或使用Element UI组件来实现这一功能。下面我们将分别介绍这两种方法&#xff0c;并对比…

吴恩达深度学习笔记(6)

正交化 为了提高算法准确率&#xff0c;我们想到的方法 收集更多的训练数据增强样本多样性使用梯度下降将算法使算法训练时间更长换一种优化算法更复杂或者更简单的神经网络利用dropout 或者L2正则化改变网络框架更换激活函数改变隐藏单元个数 为了使有监督机制的学习系统良…

vue使用jquery的ajax,页面跳转

一、引入jquery依赖 打开终端更新npm npm install -g npm 更新完后引入输入npm install jquery 加载完后 在最外层的package.json文件中加入以下代码 配置好后导入jquery 设置变量用于接收服务器传输的数据 定义ajax申请数据 服务器的Controller层传输数据 &#xff08;…

【VUE小型网站开发】初始环境搭建

1. 初始化VUE项目 1.1 创建vue项目 1.2 删除多余的界面 根据自己情况删除红框内的文件 清理app页面代码 1.3 引入vue-router 1.3.1 下载vue-router npm install vue-router1.3.2 配置vue-router 在 main.js 或 main.ts 中引入 vue-router import ./assets/main.css im…

Android 图片相识度比较(pHash)

概述 在 Android 中&#xff0c;要比对两张 Bitmap 图片的相似度&#xff0c;常见的方法有基于像素差异、直方图比较、或者使用一些更高级的算法如 SSIM&#xff08;结构相似性&#xff09;和感知哈希&#xff08;pHash&#xff09;。 1. 基于像素的差异比较 可以逐像素比较…

【SQL】写SQL查询时,常用到的日期函数

我们在做SQL的查询&#xff0c;日期函数是我们经常会用得到的函数&#xff0c;可以方便调用用于处理日期和时间数据。 以下是一些常见的日期函数及其用法示例&#xff1a; 1. 直接报出日期和时间 CURRENT_DATE&#xff1a;返回当前日期。NOW()&#xff1a;返回当前日期和时间…