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

vue - 常见的性能优化

在这里插入图片描述

文章目录

    • vue使用中常见的性能优化
      • 1, v-for 遍历避免同时使用 v-if
      • 2, 如果需要使用v-for给每项元素绑定事件时 可以使用事件代理**
      • 3, 一些数据不做响应式
      • 4,一些页面采用`keep-alive`缓存组件
      • 5,第三方UI库按需导入
      • 6,列表数据的懒加载 上滑加载分页数据
      • 7,变量本地化
      • 8,事件的销毁

vue使用中常见的性能优化


1, v-for 遍历避免同时使用 v-if

在 Vue2 中 v-for 优先级更高,所以编译过程中会把列表元素全部遍历生成虚拟 DOM,再来通过 v-if 判断符合条件的才渲染,就会有多余的逻辑判断和造成性能的浪费,因为我们希望的是不符合条件的虚拟 DOM都不要生成;

1,为了过滤一个列表中的项目 (比如 v-for="user in users" v-if="user.isActive")。在这种情形下,可以将 users 替换为一个计算属性或者方法 (比如 activeUsers),让其返回过滤后的列表;

<ul><liv-for="user in activeUsers":key="user.id">{{ user.name }}</li>
</ul>methods:{// 方法activeUsers(){//在这里面处理需要显示的数据  然后返回筛选过的列表}
}

2,为了避免渲染本应该被隐藏的列表 (比如 v-for="user in users" v-if="shouldShowUsers")。这种情形下,请将 v-if 移动至容器元素上 (比如 ul、ol)。

<ul v-if="shouldShowUsers"><liv-for="user in users":key="user.id">{{ user.name }}</li>
</ul>

在 Vue3 中 v-if 的优先级更高,就意味着当判断条件是 v-for 遍历的列表中的属性的话,v-if 是拿不到的;

注意:永远不要把 v-if 和 v-for 同时用在同一个元素上。

2, 如果需要使用v-for给每项元素绑定事件时 可以使用事件代理**

事件代理的本质就是利用事件冒泡到父元素的特性。这样就可以不用在循环的节点上每一个都加事件了;如下:

在父元素ul上面添加点击事件,如过需要传参的话 只需要添加自定义属性即可,比如下面的 id属性

  <!--  使用事件委托进行处理和传参 添加自定义属性id --><ul class="weekdays" @click="debounce($event)"><li v-for="(item, index) in dayList" :key="index" :id="index" >{{ item.day }}</li></ul>
	// 事件委托处理debounce(event) {if (event.target && event.target.nodeName == "LI") {// 现在就可以拿到当前的节点 所以就能拿到里面的属性和数据console.log("我点击的是:", event.target);}},

事件代理好处有2 个
1,将事件处理程序代理到父节点,减少内存占用率;
2,动态生成子节点时能自动绑定事件处理程序到父节点;

3, 一些数据不做响应式

一些数据不做响应式 比如会员列表、商品列表之类的,只是纯粹的数据展示,不会有任何动态改变的场景下,就不需要对数据做响应化处理,可以大大提升渲染速度;

可以使用 Object.freeze() 方法冻结一个对象,该方法冻结的对象不能被修改;即不能向这个对象添加新属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值,以及该对象的原型也不能被修改;

export default {data: () => ({userList: []}),async created() {const users = await axios.get("/api/users");this.userList = Object.freeze(users);}
};

Vue2 的响应式源码地址:src/core/observer/index.js - 144行 是这样的:

export function defineReactive (...){// getOwnPropertyDescriptor 返回指定对象上一个自有属性对应的属性描述符// 也就是直接赋予该对象的属性,不需要从原型链上进行查找的属性const property = Object.getOwnPropertyDescriptor(obj, key)判断configurable``false`不做处理if (property && property.configurable === false) {return}...
}

可以看到一开始就判断 configurablefalse 的直接返回不做响应式处理;

configurable``false` 表示这个属性是不能被修改的,而冻结的对象的 `configurable` 就是为 `false

这是vue正常定义在data里面的数据,会自动把下面的所有属性都添加get和set属性,有多少就添加多少:

在这里插入图片描述

开始冻结对象

freList是请求后端的列表数据;

  created() {this.dayList = Object.freeze(freList)console.log("daylist:",this.dayList);},

可以看出已经没有get和set属性了,但同时这些数据也不具备响应式了;

在这里插入图片描述

4,一些页面采用keep-alive缓存组件

比如在表单输入页面进入下一步后,再返回上一步到表单页时要保留表单输入的内容、比如在列表页>详情页>列表页,这样来回跳转的场景等;

基础使用:

	如果需要缓存整个项目,则如下设置(直接包裹根router-view即可)<keep-alive><router-view> </router-view></keep-alive>缓存部分页面或者组件,使用route.meta属性<keep-alive><router-view v-if="$route.meta.keepAlive"></router-view></keep-alive><router-view v-if="!$route.meta.keepAlive"></router-view>注:<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。<keep-alive><component :is="view"></component></keep-alive> 

注意: 配置了keepAlive的页面,在再次进入时不会重新渲染(第一次进来时会触发所有钩子函数),该页面内的组件同理不会再次渲染。

而这可能会导致该组件内的相关操作(那些每次都需要重新渲染页面的操作:如父子组件间的传值)不再生效。 这一点可能会导致一些莫名其妙而又无从查证的bug;

vue2.1.0 新增了include,exclude俩个属性,允许组件有条件的缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示。

    <!-- 逗号分隔字符串 --><keep-alive include="a,b"><component :is="view"></component></keep-alive><!-- 正则表达式 (需要 `v-bind`绑定) --><keep-alive :include="/a|b/"><component :is="view"></component></keep-alive><!-- 数组 (需要 `v-bind`绑定) --><keep-alive :include="['a', 'b']"><component :is="view"></component></keep-alive>

注:匹配首先检查组件自身的 name 选项,如果 name 选项不可用,则匹配它的局部注册名称 (父组件 components 选项的键值)。匿名组件不能被匹配。

动态判断,使用v-bind:include

<keep-alive :include="includedComponents"><router-view></router-view>
</keep-alive>includedComponents动态设置即可  

使用beforeRouteLeave或者afterEach中进行拦截处理

如在项目在Category组件中的设置:
beforeRouteLeave(to,from,next){if(to.name=='DemoIndex'){if(!from.meta.keepAlive){from.meta.keepAlive=true}next()}else{from.meta.keepAlive=falseto.meta.keepAlive=falsenext()}
},
在beforeRouteLeave中to.name根据具体的路由进行动态缓存设置

使用keepAlive后生命周期变化(重要):

首次进入缓存页面:beforeRouteEnter --> created --> mounted --> activated --> deactivated
再次进入缓存页面:beforeRouteEnter --> activated --> deactivated

注:
1、这里的activated非常有用,因为页面被缓存时,created,mounted等生命周期均失效,你若想进行一些操作,那么可以在activated内完成(下面会举个栗子:列表页回到上次浏览位置)
2、activated keep-alive组件激活时调用,该钩子在服务器端渲染期间不被调用。
3、deactivated keep-alive组件停用时调用,该钩子在服务端渲染期间不被调用。

5,第三方UI库按需导入

比如 vantUi, element-ui库的按需引入;见这篇文章

6,列表数据的懒加载 上滑加载分页数据

列表数据的懒加载滚动条上划到底时开始请求下一页的数据,尽量配合防抖函数使用,防止一瞬间请求的次数太多。

如下代码

这边我用的是vue3写的,vue2只是获取节点的方式不一样,其他都一样的;

onMounted(() => {// 获取滚动容器的节点let containerEle = showContentEl.value;if (!containerEle) return;// 监听滚动条containerEle.addEventListener("scroll", function () {const clientHeight = containerEle.clientHeight;const scrollTop = parseInt(containerEle.scrollTop);const scrollHeight = containerEle.scrollHeight;// 判断是否滚动条是否滚动到底  (-1是为了控制误差)if (clientHeight + scrollTop >= scrollHeight - 1) {// 开始防抖请求数据debounceLoadMaterialList();}});
});<template><div class="container"><div class="list">展示的列表数据</div></div>
</template>

设置接口防抖:

import * as _ from "lodash";
// 设置接口防抖
const debounceLoadMaterialList = _.debounce(loadMaterialList, 500);

7,变量本地化

简单说就是把会多次引用的变量保存起来,因为每次访问 this.xx 的时候,由于是响应式对象,所以每次都会触发 getter,然后执行依赖收集的相关代码,如果使用变量次数越多,性能自然就越差;

从需求上说在一个函数里一个变量执行一次依赖收集就够了,可是很多人习惯性的在项目中大量写 this.xx,而忽略了 this.xx 背后做的事,就会导致性能问题了;

比如下面vue2的例子

<template><div :style="{ opacity: number / 100 }"> {{ result }}</div>
</template>
<script>
import { someThing } from '@/utils'
export default {props: ['number'],computed: {base () { return 100 },result () {let base = this.base, number = this.number // 保存起来  -- 变量本地化for (let i = 0; i < 1000; i++) {number += someThing(base) // 避免频繁引用 this.xx}return number}}
}
</script>

8,事件的销毁

Vue 组件销毁时,会自动解绑它的全部指令及事件监听器,但是仅限于组件本身的事件;

而对于定时器addEventListener 注册的监听器等,就需要在组件销毁的生命周期钩子中手动销毁或解绑,以避免内存泄露;

<script>
export default {created() {this.timer = setInterval(this.refresh, 2000)addEventListener('touchmove', this.touchmove, false)},beforeDestroy() {clearInterval(this.timer)this.timer = nullremoveEventListener('touchmove', this.touchmove, false)}
}
</script>

相关文章:

vue - 常见的性能优化

文章目录 vue使用中常见的性能优化1&#xff0c; v-for 遍历避免同时使用 v-if2&#xff0c; 如果需要使用v-for给每项元素绑定事件时 可以使用事件代理**3&#xff0c; 一些数据不做响应式4&#xff0c;一些页面采用keep-alive缓存组件5&#xff0c;第三方UI库按需导入6&#…...

微服务系列文章 之 Nginx服务状态监控的方法

在Nginx的插件模块中有一个模块stub_status可以监控Nginx的一些状态信息&#xff0c;默认安装可能没有这个模块&#xff0c;手动编译的时候加一下即可。 1. 模块安装 先使用命令查看是否已经安装这个模块&#xff1a; [rootihxb123Z nginx]# ./nginx -V (V大写会显示版本号和…...

【网络系统集成】路由器实验

1.实验名称:路由器RIP协议配置 2.实验目的 在PacketTracer中进行模拟实验,配置RIP协议,验证RIP协议更新时间及路由状态变化,加深对路由器RIP协议相关知识的理解与掌握。 3.实验内容 (1)拓扑结构图 (2)ip地址分配与端口分配...

【mac 安装Miniconda】

1.下载Miniconda 注意mac是什么版本&#xff0c;m1下载m1版本 https://docs.conda.io/en/latest/miniconda.html#macos-installers 2.安装Miniconda 在下载文件所在目录下打开终端&#xff0c;输入一下命令&#xff1a; bash Miniconda3-latest-MacOSX-x86_64.sh 一路回车&…...

螺栓疲劳计算-风电行业,参考GL2010, ST0361,1993-1-9

由于不想再重新排版了&#xff0c;于是转成了图片。...

QT学习之旅 - QThread多线程

文章目录 首先是主线程 其次是一个程序 通过一个QThread来放入程序 进阶一点: 手动开启关闭线程俩个线程 其实QT中的thread(线程)是很容易的 首先是主线程 #include "mainwindow.h" #include "ui_mainwindow.h"#include <QDebug>MainWindow::MainWin…...

PROFINET转TCP/IP网关TCP/IP协议的含义是

大家好&#xff0c;今天要和大家分享一款自主研发的通讯网关&#xff0c;远创智控YC-PN-TCPIP。这款网关可是集多种功能于一身&#xff0c;PROFINET从站功能&#xff0c;让它在通讯领域独领风骚。想知道这款网关如何实现PROFINET和TCP/IP网络的连接吗&#xff1f;一起来看看吧&…...

计算机网络基础第六章

一、应用层概述 1.1 网络应用模型 1.1.1 客户/服务器(C/S)模型 1.1.2 P2P模型 二、域名解析系统——DNS系统 2.1 域名 2.2 域名服务器 2.3 域名解析过程 三、文件传输协议——FTP 3.1 FTP服务器和用户端 3.2 FTP工作原理 四、电子邮件 4.1 电子邮件系统概述 4.2 简单邮件传送…...

MobPush:Android客户端SDK厂商通道回执配置指南

华为厂商回执配置 登录华为AppGallery Connect网站。在左侧菜单点击增长 - 推送服务&#xff0c;进入推送服务页面后&#xff0c;点击配置页签&#xff0c;检查应用回执状态&#xff0c;如未开通请点击右侧开通按钮。 如已开通&#xff0c;点击修改按钮&#xff0c;弹出“选择…...

Karmada: Open, Multi-Cloud, Multi-Cluster Kubernetes Orchestration

Karmada是一个开源的多云应用编排和管理平台&#xff0c;旨在帮助用户在多个云提供商之间无缝地部署、编排和管理应用程序。 Karmada&#xff08;Kubernetes Armada&#xff09;是一个Kubernetes管理系统&#xff0c;它使您能够在多个Kubernetes集群和云环境中运行云原生应用程…...

arcgis拓扑检查

不能有悬挂点 不能有伪结点***路网处理很重要&#xff0c;看研究吧。 一直默认到最后。 导入要素类&#xff0c;单个 toupu2右键新建拓扑&#xff08;T&#xff09; 一般选不能有悬挂点&#xff0c;不能重叠。 一路默认 是 拉进图层可视化 线要素的话记得添加字段length&#…...

icp许可证 办理流程(icp资质申请条件)

icp许可证 办理流程(icp资质申请条件)是什么&#xff1f; ICP经营许可证是可以线上无忧办理的&#xff0c;包下证&#xff0c;流程也很简单&#xff0c;只需要你提供企业营业执照、法人身份证这些基础材料就可以。加急10-20工作日拿证&#xff0c;普通20-60工作日拿证。 在了解…...

三菱PLC 控制灯一秒钟交替闪烁

三菱PLC中常用的特殊继电器&#xff1a; M8000 上电一直ON标志 M8002 上电导通一次 M8004 PLC出错 M8005 PLC备用电池电量低标志 M8011 10ms时钟脉冲 M8012 100ms时钟脉冲 M8013 1s时钟脉冲 M8014 1min时钟脉冲 M8034…...

金融数据库的战场,太平洋保险和OceanBase打了场胜仗

点击关注 文丨刘雨琦 “数据库的国产替代&#xff0c;必须经过严格的考虑&#xff0c;保证不会出错&#xff0c;所以大多数企业的领导层选择按兵不动或者简单扩容。因为不换就不会错&#xff0c;选了很久如果选错&#xff0c;还可能会出现重大事故。” 某银行数据库技术人员…...

IP协议【图解TCP/IP(笔记九)】

文章目录 IP即网际协议IP相当于OSI参考模型的第3层网络层与数据链路层的关系 IP基础知识IP地址属于网络层地址路由控制■ 发送数据至最终目标地址■ 路由控制表 数据链路的抽象化IP属于面向无连接型 IP即网际协议 TCP/IP的心脏是互联网层。这一层主要由IP&#xff08;Internet…...

C#仿热血江湖

目录 1 定义属性 2 GClass86_0 3 Int32 4 List 5 NpcID 定义属性 private int _NpcID; private GClass86 gclass86_0 = new GClass86(); private int int_0;...

Nginx静态资源部署

要在 Nginx 上部署静态资源&#xff0c;可以按照以下步骤进行操作&#xff1a; 确保已经安装并配置好 Nginx。如果还没有安装&#xff0c;可以参考 Nginx 的官方文档进行安装和配置。 将静态资源文件复制到 Nginx 的默认静态文件目录下。默认情况下&#xff0c;Nginx 的静态文…...

javaee jstl表达式

jstl是el表达式的扩展 使用jstl需要添加jar包 package com.test.servlet;import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;import javax.servlet.ServletException; import javax.servlet…...

ChatGPT是否具有记忆能力?

ChatGPT在某种程度上具有记忆能力&#xff0c;但它的记忆能力有限且不像人类的记忆那样全面和持久。以下是对ChatGPT的记忆能力的详细分析&#xff1a; 1. 上下文记忆&#xff1a;ChatGPT可以在对话过程中记住先前的对话历史&#xff0c;以便更好地理解和回应后续的问题。通过…...

ARP协议(地址分析协议)

系列文章目录 数通王国历险记&#xff08;4&#xff09; 目录 前言 一&#xff0c;什么是地址解析协议&#xff08;ARP&#xff09; 二&#xff0c;封装和解封装 三&#xff0c;为什么需要地址解析协议&#xff08;ARP&#xff09; 四&#xff0c;ARP的验证实验 4.1&#x…...

查找 Vue 项目中未使用的依赖

在 Vue 项目中查找未使用的依赖可以通过以下几种方法&#xff1a; 1. 使用 depcheck 工具 depcheck 是一个专门用于查找项目中未使用依赖的工具。 安装&#xff1a; bash npm install -g depcheck使用&#xff1a; bash depcheck它会列出&#xff1a; 未使用的依赖缺失…...

yaffs2目录搜索上下文数据结构struct yaffsfs_dirsearchcontext yaffsfs_dsc[] 详细解析

1. 目录搜索上下文&#xff08;Directory Search Context&#xff09; struct yaffsfs_dirsearchcontext 是 YAFFS2 文件系统中用于 目录遍历操作 的核心数据结构&#xff0c;专门管理 readdir() 等目录操作的状态。 结构体定义&#xff08;典型实现&#xff09; struct yaf…...

设计模式基础概念(行为模式):模板方法模式 (Template Method)

概述 模板方法模式是一种行为设计模式&#xff0c; 它在超类中定义了一个算法的框架&#xff0c; 允许子类在不修改结构的情况下重写算法的特定步骤。 是基于继承的代码复用的基本技术&#xff0c;模板方法模式的类结构图中&#xff0c;只有继承关系。 需要开发抽象类和具体子…...

瀚文(HelloWord)智能键盘项目深度剖析:从0到1的全流程解读

瀚文&#xff08;HelloWord&#xff09;智能键盘项目深度剖析&#xff1a;从0到1的全流程解读 一、项目整体概述 瀚文&#xff08;HelloWord&#xff09;智能键盘是一款多功能、模块化的智能机械键盘&#xff0c;由三大部分组成&#xff1a;键盘输入模块、可替换的多功能交互…...

配置git命令缩写

以下是 Git 命令缩写的配置方法及常用方案&#xff0c;适用于 Linux/macOS/Windows 系统&#xff1a; &#x1f527; 一、配置方法 1. 命令行设置&#xff08;推荐&#xff09; # 基础命令缩写 git config --global alias.st status git config --global alias.co che…...

AI编程提示词

你是 IDE 的 AI 编程助手&#xff0c;遵循核心工作流&#xff08;研究 -> 构思 -> 计划 -> 执行 -> 评审&#xff09;用中文协助用户&#xff0c;面向专业程序员&#xff0c;交互应简洁专业&#xff0c;避免不必要解释。[沟通守则] 1. 响应以模式标签 [模式&#…...

统信桌面专业版如何使用python开发平台jupyter

哈喽呀&#xff0c;小伙伴们 最近有学员想了解在统信UOS桌面专业版系统上开发python程序&#xff0c;Anaconda作为python开发平台,anaconda提供图形开发平台,提供大量的开发插件和管理各种插件的平台&#xff0c;但是存在版权问题&#xff0c;有没有其他工具可以替代Anaconda呢…...

智能终端与边缘计算按章复习

第1章&#xff1a;智能终端与边缘计算概述 简述计算机网络和Web技术发展过程中&#xff0c;信息和运算从用户本地向Web服务器迁移的趋势&#xff0c;并解释这一过程如何逐步形成了如今的云计算形态。 随着计算机网络和Web技术的不断发展&#xff0c;信息和运算的重心发生了显著…...

分布式Session处理的五大主流方案解析

在分布式环境下&#xff0c;Session 处理的核心挑战是确保用户请求在不同服务器间流转时能保持会话状态一致。以下是主流解决方案及优缺点分析&#xff1a; &#x1f510; 一、集中存储方案&#xff08;主流推荐&#xff09; Redis/Memcached 存储 原理&#xff1a;将 Session…...

每日Prompt:双重曝光

提示词 新中式&#xff0c;这幅图像将人体头像轮廓与山水中式建筑融为一体&#xff0c;双重曝光&#xff0c;体现了反思、内心平静以及人与自然相互联系的主题&#xff0c;靛蓝&#xff0c;水墨画&#xff0c;晕染&#xff0c;极简...