Vue 性能革命:揭秘前端优化的终极技巧;Vue优化技巧,解决Vue项目卡顿问题

目录

Vue优化路径

一、使用key

二、使用冻结对象

三、使用函数式组件

四、使用计算属性

五、使用非实时绑定的表单项

六、保持对象引用稳定

6.1、保持对象引用稳定定义

6.2、保持对象引用稳定与不稳定的例子

6.3、vue2判断数据是否变化是通过hasChanged函数实现的

①为什么在x === y成立的时候,还要做一个return x === 0 && 1 / x !== 1 / (y as number)的判断?

②为什么在 x === y 不成立的时候,还要做一个x === x || y === y的判断?

七、使用v-show替代v-if

八、使用延迟装载(defer)

九、使用keep-alive

十、长列表优化

十一、打包体积优化

十二、总结与相关资源


Vue优化路径

一、使用key

        也就是使用v-for这样通过循环生成的列表,应给每个列表项一个稳定且唯一的key,这样有利于在列表变动时,尽量少的删除、新增、改动元素。

二、使用冻结对象

        在不需要改动的数据时(比如只读的数据:面向顾客的商品列表等),将对象冻结。例如:

var obj = { a : 1, b : 2}

Object.freeze(obj)

obj.a = 3 // 无效,obg.a依然为1

// 此时obj的属性无法访问,自然也无法通过Object.defineProperty来实现响应式

Object.isFrozen(obj) // 返回true,检查是否冻结

        冻结的对象不会被响应化,节约了observe该对象每个属性的资源(添加getter和setter)

        举一个例子,可以做一个demo实际体验一下效率的区别,做个页面放两个按钮,分别绑定loadFrozenDatas和loadNormalDatas方法,就能明显感受到生成同样的数据,冻结的对象生成速度显著快于不冻结的对象生成。

data() {
    return{
        normalDatas: [],
        freezeDatas: [],
    };
},
methods: {
    loadNormalDatas(){
        this.normalDatas = this.getDatas(); console.log("normalDatas", this.normalDatas);
    },
    loadFrozenDatas() {
        this.freezeDatas = Object.freeze(this.getDatas()); console.log("freezeDatas", this.freezeDatas);
    },
    getDatas(){
        const result = [];
        for (var i = 0; i < 1000000; i++) {
            result.push({
                id: i,
                name:`name${i}`,
                address:{
                    city:`city${i}`,
                    province:`province${i}`,
                },
            });
        }
        return result;
    },
}

observe中会调用Object.defineProperty(),通过属性描述符为对象的每个属性实现响应式

属性描述符详情请看:属性描述符初探——Vue实现数据劫持的基础

三、使用函数式组件

        在Vue.js中,函数式组件是一种没有状态和实例的概念的组件。函数式组件主要用于声明性地描述UI,它们接受 props 作为输入,并返回一个Vue元素树作为输出。

        函数式组件不会通过new VueComponent生成新的vue实例,不会加入到vue的组件树中,只做页面渲染,节省性能。

// Vue 2中的函数式组件:

Vue.component('my-functional-component', {
  functional: true,
  render: function (createElement, context) {
    // 使用createElement创建元素
    return createElement('div', context.props.text);
  }
});


// Vue 3中的函数式组件:

import { h, FunctionalComponent } from 'vue';

const MyFunctionalComponent: FunctionalComponent = (props, { slots }) => {
  return h('div', props.text, slots().default);
};

export default MyFunctionalComponent;

四、使用计算属性

        计算属性可以缓存(只有所依赖的数据变化了才会重新计算),如果模版中数据会使用多次,就可以使用计算属性。

五、使用非实时绑定的表单项

        双向绑定会导致任意一端修改数据均会导致重渲染rerender,在不需要双向绑定的位置(比如只开放只读数据)或者不需要保持实时数据双向绑定的情况下(比如输入框内容和页面某元素绑定,输入过程中每按一次键盘都会导致一次重新渲染)不使用v-model。

        也可以通过v-model.lazy来允许某一时间内数据与表单内容不一致,也就是从监听@input变成了监听@change。

六、保持对象引用稳定

6.1、保持对象引用稳定定义

        大多数情况下,vue触发重渲染的时机是依赖数据发生变化的时机,若数据没有变化,哪怕重新给数据赋值,vue也不会做出反应。

        因此,哪怕读取属性所属的对象值没变,但是引用变了,也会导致页面重新渲染。 

6.2、保持对象引用稳定与不稳定的例子

        现在页面上渲染了一个表格,由一系列对象数据生成。如果要在数据库增加一行。那么读取数据库增加的数据,并将其添加到现有的表格数据中,效率会比直接从数据库读取全部数据,然后赋值给表格绑定的数据上要高。

        因为读取增加的数据,然后修改表格绑定的数据,只有变化的数据会重新渲染,原先有的表格行不会重渲染,可如果直接把增加后的全部数据(一个引用不同的新对象)赋值给表格绑定的数据,就会导致所有行全部重新渲染,哪怕大多数行数据并没有变化

6.3、vue2判断数据是否变化是通过hasChanged函数实现的

function hasChanged(x : unknown, y : unknown) :boolean{
  if (x === y){
    return x === 0 && 1 / x !== 1 / (y as number)
  } else {
    return x === x || y === y
  }
}

        这里x与y分别是新值和旧值。

        正常情况下,如果x===y,代表没有改变,返回false,反之则返回true。

①为什么在x === y成立的时候,还要做一个return x === 0 && 1 / x !== 1 / (y as number)的判断?

        +0 === -0的判断恒为true,但二者实际不相等。所以先判断x是否为0+或0-,如果不是,则直接触发短路返回false,如果是,就通过求倒数,比较倒数是否相等,如果均为0+或均为0-,则依然返回false,若倒数为Infinity和-Infinity,这样就会返回true,从而排除从0+变为0-,但是却新旧值却相等的情况。

②为什么在 x === y 不成立的时候,还要做一个x === x || y === y的判断?

        因为如果NaN === NaN的判断恒为false,所以哪怕不相等,还要做一下自判断,若新旧值都是NaN,则返回false。排除x与y都为NaN,但是新旧值却不相等的情况。

七、使用v-show替代v-if

        对于频繁切换显示状态的元素,使用v-show可以保证虚拟dom树的稳定,尤其是对于那些内部包含大量dom元素的节点,这一点极其重要。

        DOM树只与布局有关,与显示与否无关。使用v-show渲染的元素,不管返回值是什么,都会添加到dom树中,但是使用v-if渲染的元素,只有为true的时候才会添加到DOM树中。

八、使用延迟装载(defer)

        HTML中的<script>标签有一个可选的defer属性。当脚本设置了defer属性后,它会被告知浏览器在文档解析完成后再执行这个脚本,而不是立即执行。

        对于图片和其他资源,可以使用 v-lazy-image 或 v-lazy-component 这样的 Vue 指令来实现懒加载。

<!-- 在模板中使用 -->
<img v-lazy="imageSrc" alt="Lazy Image">

        使用像 vue-lazyload 这样的库来实现图片和组件的懒加载。 

// 安装 vue-lazyload
npm install vue-lazyload --save

// 在 main.js 中使用
import Vue from 'vue';
import VueLazyload from 'vue-lazyload';

Vue.use(VueLazyload, {
  preLoad: 1.64,
  error: 'error.png',
  loading: 'loading.png',
  attempt: 1
});

九、使用keep-alive

        keep-alive 是 Vue 的一个内置组件,用于缓存不活动的组件实例,避免重复创建和销毁组件,从而提高性能。这在单页面应用(SPA)中特别有用,可以保持用户状态和避免不必要的重新渲染。

<!-- 在路由出口使用 -->
<router-view v-if="$route.meta.keepAlive"></router-view>
<keep-alive>
  <router-view v-if="!$route.meta.keepAlive"></router-view>
</keep-alive>

        这里会根据路由的 meta 属性决定是否使用 keep-alive。

十、长列表优化

        海量数据渲染容易导致卡顿,除了可以运用第六点保持引用对象稳定外,Vue还提供了几种方法来优化长列表的渲染:

  • 虚拟滚动(Virtual Scrolling):只渲染可视区域内的元素,而不是渲染整个列表。可以使用 vue-virtual-scroll-list 或 vue-virtual-scroller 等库来实现。
  • 分页或无限滚动:将数据分批次加载,而不是一次性加载所有数据。
  • 节流(Throttle)和防抖(Debounce):在处理滚动事件等频繁触发的操作时,使用节流或防抖技术减少事件处理的频率。

        此外,element plus也提供了虚拟化组件,用来处理海量数据的渲染问题

十一、打包体积优化

        减少最终打包文件的大小可以提高应用的加载速度和性能。常见方法包括:

  1. 代码分割(Code Splitting):使用 Webpack 的动态 import() 语法来实现代码分割,只加载用户实际需要的代码。
  2. Tree Shaking:移除未使用的代码,Webpack 等现代打包工具可以自动进行 Tree Shaking
  3. 使用 Vue CLI 的优化选项:Vue CLI 提供了多种优化配置,如 vue-cli-service build --report 可以生成报告,帮助分析打包体积。
  4. 移除 console.log:在生产环境中,确保移除所有的 console.log 语句,因为它们会增加打包体积。
  5. 使用 Terser 或 UglifyJS 压缩 JavaScript:这些工具可以压缩 JavaScript 代码,减少文件大小。

十二、总结与相关资源

        Vue在处理少量数据和有限dom的情况下技术已经非常成熟了,但现在随着AI时代的到来,海量数据场景会越来越多,Vue优化技巧也是必备技能。

        博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        更多优质内容,请关注:

JS底层逻辑:

        最细最有条理解析:事件循环(消息循环)是什么?进程与线程的定义、关系与差异

        路由通配符,小小的字符有大大的作用,你真的熟悉吗? 

        管理数据必备!侦听器watch用法详解

        什么是深拷贝?深拷贝和浅拷贝有什么区别

JS语法篇:

        属性描述符初探——Vue实现数据劫持的基础

        你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

        对象数据的读取,看这一篇就够了!

        通过array.every()实现数据验证、权限检查和一致性检查,array.some与array.every的区别

        通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理

        通过array.map()实现数据转换、创建派生数组、异步数据流处理、搜索和过滤等需求

        通过array.reduce()实现数据汇总、条件筛选和映射、对象属性的扁平化、转换数据格式等

        通过array.filter()实现数组的数据筛选、数据清洗和链式调用

巧妙算法与窍门:

        多维数组操作,不要再用遍历循环foreach了,来试试数组展平的小妙招!

        别再用双层遍历循环来做新旧数组对比,寻找新增元素了!

        shpfile转GeoJSON且控制转化精度;如何获取GeoJSON?GeoJson结构详解

        Mapbox添加行政区矢量图层、分级设色图层、自定义鼠标悬浮框、添加天地图底图等

Element plus拓展:

        通过el-tree自定义渲染网页版工作目录,实现鼠标悬浮显示完整名称等

        el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

        el-table中如何添加渐变色带、多色色带

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring AOP、Spring MVC工作原理、发展演变、常用注解

Spring AOP 概念 AOP全称为Aspect Oriented Programming&#xff0c;表示面向切面编程。切面指的是将那些与业务无关&#xff0c;但业务模块都需要使用的功能封装起来的技术。 AOP基本术语 **连接点&#xff08;Joinpoint&#xff09;&#xff1a;**连接点就是被拦截到的程序执…

智能文档革新:合合信息智能文档处理平台上线基金合同抽取模型!

一、什么是基金合同&#xff1f; 基金合同是指具有平等地位主体的基金当事人在基金活动中&#xff0c;为规范其间的权利、义务&#xff0c;依意思表示一致而形成的契约或协议。《证券投资基金法》第五十二条规定&#xff0c;公开募集基金的基金合同应当包括下列内容: &#x…

软件游戏d3dcompiler_43.dll丢失怎么办,总结几种有效的方法

在使用电脑时&#xff0c;可能会碰到找不到d3dcompiler_43.dll的问题。即在使用过程中&#xff0c;突然弹出一个提示“d3dcompiler_43.dll丢失”&#xff0c;由于此文件的缺失&#xff0c;部分程序将无法启动。为恢复正常使用&#xff0c;我们需要修复此文件。接下来&#xff0…

【C++】 解决 C++ 语言报错:Undefined Reference

文章目录 引言 未定义引用&#xff08;Undefined Reference&#xff09;是 C 编程中常见的错误之一&#xff0c;通常在链接阶段出现。当编译器无法找到函数或变量的定义时&#xff0c;就会引发未定义引用错误。这种错误会阻止生成可执行文件&#xff0c;影响程序的正常构建。本…

Java项目:基于SSM框架实现的中小企业人力资源管理系统【ssm+B/S架构+源码+数据库+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的中小企业人力资源管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简…

matlab 绘制高等数学中的二维函数示例

matlab 绘制高等数学中的二维函数示例 绘制高等数学中的二维函数示例绘制结果 绘制高等数学中的二维函数示例 clc,clear,close all; % 定义方程 eqn (x, y) (x.^2 y.^2).^3 - y.^4;% 绘制方程曲线和坐标轴 ezplot(eqn, [-2, 2, -2, 2]) hold on % 在同一图形中保持绘图% 绘…

国际上备考所有云计算/IT证书的五大优质免费课程网站

最近越来越多的小伙伴来问小李哥&#xff0c;小李哥亚马逊云科技AWS认证大满贯是在哪里上课复习的呢&#xff1f;全部上付费课程那不是一笔巨款吗&#xff1f;小李哥这次来盘点备考国际上IT证书的5大优质免费课程网站(不只是亚马逊云科技AWS的课程&#xff0c;其他课程同样可以…

满足GMSL静电防护要求的方案

什么是GMSL&#xff1f;它是做什么用的&#xff1f;它有什么优点&#xff1f;设计GMSL防静电有啥难度&#xff1f; 带着这些疑问我们先了解下什么是GMSL。 一&#xff0e;简述 GMSL GMSL&#xff08;Gigabit Multimedia Serial Link&#xff09;即千兆多媒体串行链路&#xf…

odoo 物联网 设备数据采集方案

图一 架构手稿(许老师专属) 图二 架构简图 部署 方案一&#xff1a; odoo业务数据库与设备采集数据库使用一个instance。 缺点&#xff1a;重启pg服务相互影响。 方案二&#xff1a; odoo业务数据库与设备采集数据库独立部署&#xff0c;使用两个instance。 优点&#xff1a;…

一个使用率超高的大数据实验室是如何练成的?

厦门大学嘉庚学院“大数据应用实训中心”&#xff08;以下简称“实训中心”&#xff09;自2022年建成以来&#xff0c;已经成为支撑“大数据专业”复合型人才培养的重要支撑&#xff0c;目前实训中心在专业课程实验教学、项目实训、数据分析类双创比赛、毕业设计等方面都有深入…

CVPR2024自动驾驶轨迹预测方向的论文整理

2024年自动驾驶轨迹预测方向的论文汇总 1、Producing and Leveraging Online Map Uncertainty in Trajectory Prediction 论文地址&#xff1a;https://arxiv.org/pdf/2403.16439 提出针对在线地图不确定性带给轨迹预测的影响对应的解决方案。 在轨迹预测中&#xff0c;利用在…

vscode连接SSH——连接学校服务器,使用conda配置个人环境并使用

服务器的连接 在vscode远程资源管理中配置配置文件&#xff0c;如下图&#xff1a; 然后点击左下角进行连接&#xff1a; 点击需要连接的服务器&#xff0c;输入对应密码即可登录成功。 服务器上创建自己的环境 确保服务器上已安装anaconda。 先查看服务器上的conda信息&…

Linux_共享内存通信

目录 1、共享内存原理 2、申请共享内存 2.1 ftok 2.2 测试shmget、ftok 2.3 查看系统下的共享内存 3、关联共享内存 3.1 测试shmat 4、释放共享内存 4.1 测试shmctl 5、实现共享内存通信 6、共享内存的特性 结语 前言&#xff1a; 在Linux下&#xff0c;有一…

jenkins在使用pipeline时,为何没有方块形视图

项目场景&#xff1a; 安装完Jenkins时后&#xff0c;通过pipeline创建的项目任务。 问题描述 在立即构建后&#xff0c;没有显示每个阶段的视图。 原因分析&#xff1a; 原因是&#xff0c;刚安装的Jenkins&#xff0c;这个视图不是Jenkins自带的功能&#xff0c;而必须安装…

Cannot resolve symbol ‘log`

idea里的代码log变红色&#xff0c;是因为缺少Lombok插件。 安装lombok插件即可。安装完应用&#xff0c;重启软件就好了。 依次点击菜单栏中的 File → Settings&#xff08;Windows/Linux&#xff09; 或 IntelliJ IDEA → Preferences&#xff08;macOS&#xff09;。在设置…

设计模式探索:单例模式

1. 什么是单例模式? 定义: 单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一种全局访问点以访问该实例。常见的场景包括身份证号码、政府等需要唯一实例的情况。 单例模式通常用于那些需要在应用程序中仅存在一个实例的情况,例如配置管理器、线程池、数据…

ret2syscall简单总结

主要是自己的简单的学习总结。 知识点 关于系统调用如何传递参数问题&#xff0c;即系统调用约定&#xff08;syscall&#xff0c;int 80h&#xff0c;svc&#xff09;_int 80h intel汇编用法-CSDN博客 ret2syscall的做题思路&#xff08;以32位程序为例&#xff09; - ZikH…

2024年【山东省安全员A证】考试试卷及山东省安全员A证考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 山东省安全员A证考试试卷根据新山东省安全员A证考试大纲要求&#xff0c;安全生产模拟考试一点通将山东省安全员A证模拟考试试题进行汇编&#xff0c;组成一套山东省安全员A证全真模拟考试试题&#xff0c;学员可通过…

react 项目中预防xss攻击的插件 dompurify

一、安装 $ yarn add dompurify $ yarn add --dev types/dompurify 二、使用 import DOMPurify from dompurify;// 1、处理&#xff1a; DOMPurify.sanitize(htmlContent)// 2、之后放进 dangerouslySetInnerHTML dangerouslySetInnerHTML{{ __html: cleanHTML }} 如&#…

Django自动生成Swagger接口文档 —— Python

1. 前言 当接口开发完成&#xff0c;紧接着需要编写接口文档。传统的接口文档通常都是使用Word或者一些接口文档管理平台进行编写&#xff0c;但此类接口文档维护更新比较麻烦&#xff0c;每次接口有变更&#xff0c;需要手动修改接口文档。在实际的工作中&#xff0c;经常会遇…