Vue中的性能优化方案

目录
  • 减少响应式使用
    • 1. 使用 computed 缓存计算结果
    • 2. 本地化响应式变量
    • 3. 函数式组件(Vue2)
  • 减少 DOM 渲染压力
    • 1. DOM 频繁切换展示的情况使用 v-show
    • 2. keep-alive 缓存组件状态
    • 3. 路由懒加载
    • 4. 图片懒加载
    • 5. 组件销毁时要清除定时器、EventListener
    • 6. 列表使用唯一 key
  • 减少打包体积
    • 1. 开启 gzip 压缩
    • 2. 按需引入第三方组件

最近使用 Vue 开发的过程中使用到一些对于性能有所提升的编码方式,所以特别梳理出来,可以作为后续 Vue 开发的编码规范使用

性能优化方案主要分为三类,下面就详细讲讲这三类优化方案的应用

  • 减少响应式使用
  • 减少 DOM 渲染
  • 减少打包体积

减少响应式使用

Vue 中使用最方便的就是响应式的变量,在读取(get)对象属性的时候收集副作用函数(effect)依赖,在写入(set)属性时取出副作用函数依赖执行,但是收集依赖、触发依赖执行毕竟都会影响到性能,所以在明确知道不需要使用响应式变量的场景下,就应该减少响应式变量的使用

1. 使用 computed 缓存计算结果

computed 和普通方法的区别在于:computed 会缓存计算结果,只有当计算的内容改变的时候才会重新计算,而普通方法每次都会重新计算。所以对于有计算逻辑的取值,建议尽量都通过 computed 来封装一层

比如下面这个示例就是简单的将 props 通过 computed 封装一层后共 template 使用

const getTooltipStyle = computed((): CSSProperties => {
  return {
    color: props.color,
    fontSize: props.fontSize,
  };
});

2. 本地化响应式变量

根据 Vue 响应式变量的原理,每次访问响应式数据时,都会收集依赖,所以在需要频繁使用响应式变量的时候,可以先将响应式变量用一个本地变量存储,转换为一个非响应式的变量

在 Vue3 中可以使用 unref 这个 api 来获取到响应式变量参数本身(Vue2 中直接通过 this 赋值就好)

const tableData = ref([]) 

const unrefTableData = unref(tableData) // 本地化变量后再做大量操作
unrefTableData.forEach(item => {
  // 具体操作
})

3. 函数式组件(Vue2)

函数式组件是指:只接受一些 prop 参数,无响应式数据,无实例的组件,主要应用在创建简单的展示组件,比如标题 header、纯展示的表单等等。因为没有响应式数据和实例,所以初始化速度比普通有状态的组件快很多,并且还支持返回多个节点

在 Vue2 中声明函数式组件的方式如下

<!-- template 中的声明方式 -->
<template functional>
</template>

<!-- jsx 中的声明方式 -->
Vue.component("list", {
	functional: true,
})

但是在 Vue3 中,有状态的组件性能已经大大提升,和无状态组件(函数式组件)几乎没有差异,并且有状态组件也支持了返回多个节点,所以官方也移除了 functional 定义函数式组件的方式,注意 Vue3 中是不兼容 Vue2 的函数式组件定义,所以如果未来打算升级 Vue3 的小伙伴就不建议使用函数式组件了

减少 DOM 渲染压力

1. DOM 频繁切换展示的情况使用 v-show

这是一个老身长谈的优化方案了,原理在于 v-ifv-show 实现方式的区别,对于 v-if 在不符合条件的情况下不会渲染 DOM 节点,对于 v-show 则是将各个条件情况都渲染出来,在通过 display: block / none 进行切换,所以在频繁切换 DOM 展示情况的场景下,使用 v-show 的性能会相对更好,比如一个可编辑单元格需要频繁切换编辑和保存后的状态的时候

v-show 也不是没有缺点,因为会把各个分支情况都提前渲染出来,如果节点很多并且不需要频繁切换状态,用 v-if 会是更好的选择

2. keep-alive 缓存组件状态

在 Vue 中切换组件时,组件内部的状态也会丢失,比如我们在填写一个表单的时候,切换到另外一个组件填写其他信息,在切换回之前的表单组件后,原来填写的信息会被刷新掉,这种情况下就会使用到 keep-alive 组件缓存组件状态

比较常用的做法是在 <router-view> 标签内嵌套一层 <transition> 标签增加组件切换时的过渡动画效果,再嵌套一层 <keep-alive> 标签缓存组件状态,最后使用 <component> 渲染动态组件或者元素

<router-view>
  <template #default="{ Component, route }">
    <transition>
      	<keep-alive>
           <component :is="Component" :key="route.path" />
    	</keep-alive>
    </transition>
  </template>
</router-view>

3. 路由懒加载

我们都知道 Vue 是单页面页面应用,如果在首屏加载的时候就把所有需要使用的路由都加载出来的话,那就太浪费性能了,所以使用懒加载的方式加载路由,减少首屏加载的压力,才是更合理的方案

在 vue-router 中使用路由懒加载需要通过箭头函数返回一个 import 组件的路径,这样在运行到这个组件的时候,才会运行 import 编译加载组件

const form: AppRouteRecordRaw = {
  path: "/basicForm",
  name: "BasicForm",
  component: () => import("/@/views/form/index.vue"),
  meta: {
    title: "基础表单",
  },
};

export default form;

4. 图片懒加载

图片使用懒加载的原因和路由懒加载类似,都是为了减少不必要的渲染。比如我们有一张很长的页面有很多数据或者图片需要展示,而显示屏幕的可视高度却是固定的,所以在屏幕高度外的内容完全可以等到页面需要的时候再加载,从而减少了可是屏幕区域内的渲染压力

图片懒加载的原理是:判断图片出现在当前窗口时,将 data-src 替换为 src 加载图片,比较常用三个可视区域判断方式是

  • img.getBoundingClientRect().top < document.documentElement.clientHeight(元素相对于窗口位置 < 窗体高度)
  • IntersectionObserver api,当其监听到目标元素的可见部分到达屏幕高度内,执行指定的回调函数
  • loading="lazy" 属性(目前兼容性不是特别好,参考Lazy loading - Web 性能

在 Vue 中使用图片懒加载推荐使用 vue-lazyload 这个插件,直接通过 v-lazy 这个指令就可以实现图片懒加载的效果

<ul>
  <li v-for="img in list">
    <img v-lazy="img.src" >
  </li>
</ul>

5. 组件销毁时要清除定时器、EventListener

有时我们会在项目中开启 setTimeout 来定时触发一些事件,比如定时提醒表单保存之类的需求,如果在离开组件时没有及时清除掉定时器或者是 EventListener ,很多页面堆积起来很容易造成页面卡顿和内存泄漏

常见的方案是在离开组件之前的 onBeforeUnmount 生命周期钩子中清除掉定时器和 EventListener

onBeforeUnmount(() => {
  try {
    instance?.destroy?.();
  } catch (error) {
    instanceRef.value = null;
  }
})

在清除 EventListener 要注意:移除相同的函数。以下第一种情况不能清理掉 click 事件,因为它们是不同的函数对象,需要使用第二种指向相同函数对象的方式清除

// 这种情况不生效,因为指向的是不同函数对象
input.addEventListener("click", () => console.log("Hello"))
input.removeEventListener("click", () => console.log("Hello"))

// 此时指向相同的函数对象才能清理掉 EventListener 事件
function handler() {
  console.log("Hello")
}

input.addEventListener("click", () => handler)
input.removeEventListener("click", () => handler)

6. 列表使用唯一 key

这个主要是和 diff 算法的效率有关,所以我也把它作为减少 DOM 渲染压力的一个方案。在我们使用 v-for 循环渲染内容的时候,需要为每个组件分配一个 id,这样在组件内容有更新的时候,diff 算法通过 id 能够更高效的找到变化的节点,让 dom 渲染更迅速。同时需要注意分配的 id 最好不是数组的 index,因为一旦增加或减少数组元素,index 也会发生变化,这样就失去 id 的效果了

<template v-for="schema in getSchema" :key="schema.field">
  <form-item
    :schema="schema"
    :form-props="getProps"
    :all-default-values="defaultValueRef"
  />
</template>

减少打包体积

1. 开启 gzip 压缩

gzip 一种文件压缩的格式,比较适合文本文件的压缩,通常会缩小两倍以上的体积,所以用在代码文件的压缩上非常合适

我们现在使用的打包工具还是 webpack,在 webpack 中开启 gzip 打包的话可以使用 compression-webpack-plugin 这个插件,具体配置如下

const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
  configureWebpack : {
    plugins: [
      new CompressionPlugin({
        test: /\.(js|css|json|html)&/,
        tereshold: 10 * 1024, // 超过 10 k 才压缩
      })
    ]
  }
}

开启 gzip 除了要在代码中增加配置外,还需要服务端的支持,在前端中比较常用的是 Nginx,在 Nginx 中开启 gzip 压缩的主要配置参数如下

#开启和关闭gzip模式
gzip on;

#gizp压缩起点,文件大于10k才进行压缩
gzip_min_length 10k;

# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,一般为 5,再大效果就不明显了
gzip_comp_level 5;

# 进行压缩的文件类型。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript ;

#nginx对于静态文件的处理模块,开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
gzip_static on

# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;

# 设置压缩所需要的缓冲区大小,以4k为单位,如果文件为7k则申请2*4k的缓冲区
gzip_buffers 2 4k;

# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.1;

2. 按需引入第三方组件

我们平时使用的 UI 组件一般都是大而全的,我们的项目中很少会全部使用到,所以按需引入第三方组件,能够有效减少应用包体积

以我们现在使用的 Element Plus 组件为例,使用 unplugin-vue-componentsunplugin-auto-import 这两个插件来实现(参考官方教程

首先引入两个插件

pnpm i -D unplugin-vue-components unplugin-auto-import

然后再 Webpack 配置两个插件即可

// webpack.config.js
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = {
  // ...
  plugins: [
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
}

到此这篇关于Vue中的性能优化方案的文章就介绍到这了,更多相关Vue 性能优化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅谈Vue 性能优化之深挖数组

    背景 最近在用 Vue 重构一个历史项目,一个考试系统,题目量很大,所以核心组件的性能成为了关注点.先来两张图看下最核心的组件 Paper 的样式. 从图中来看,分为答题区与选择面板区. 稍微对交互逻辑进行下拆解: 答题模式与学习模式可以相互切换,控制正确答案显隐. 单选与判断题直接点击就记录答案正确性,多选是选择答案之后点击确定才能记录正确性. 选择面板则是记录做过的题目的情况,分为六种状态(未做过的,未做过且当前选择的,做错的,做错的且当前选择的,做对的,做对的且当前选择的),用不同的样式去

  • mpvue性能优化实战技巧(小结)

    最近一直在折腾mpvue写的微信小程序的性能优化,分享下实战的过程. 先上个优化前后的图: 可以看到打包后的代码量从813KB减少到387KB,Audits体验评分从B到A,效果还是比较明显的.其实这个指标说明不了什么,而且轻易就可以做到,更重要的是优化小程序运行过程中的卡顿感,请耐心往下看. 常规优化 常规的Web端优化方法在小程序中也是适用的,而且不可忽视. 一.压缩图片 这一步最简单,但是容易被忽视.在tiny上在线压缩,然后下载替换即可. 我这项目的压缩率高达72%,可以说打包后的代码从

  • vue终极性能优化方案(解决首页加载慢问题)

    目录 前言 1.路由懒加载 2.打包文件中去掉map文件 3.CDN引入第三方库 4.gzip打包 1.npmi-Dcompression-webpack-plugin 2.在vue.config.js中配置 3.在NGINX中配置 5.终极大招,预渲染 1.cnpminstallprerender-spa-plugin--save-dev 2.vue.config.js 3.router.js 4.main.js 总结 前言 用vue开发项目上线以后,发现首页加载速度非常慢,如果项目比较大,甚

  • Vue.js九个性能优化技巧(值得收藏)

    目录 Functional components Child component splitting Local variables Reuse DOM with v-show KeepAlive Deferred features Time slicing Non-reactive data Virtual scrolling 总结 参考资料 这篇文章主要参考了 Vue.js 核心成员Guillaume Chau在 19 年美国的 Vue conf 分享的主题:9 Performance se

  • 加速vue组件渲染之性能优化

    背景 平时在用vue开发后台管理系统的时候,应该会用到大量的table这种组件,正常这种组件我们会在项目里做二次封装,然后针对表头title做参数化配置,如下: export default { data(){ return { tableTitle:[ { label:'省份', prop:'prop' }, { label:'城市', prop:'prop' }, { label:'汇总', prop:'prop', colconfig:[ { label:'下级', prop:'prop'

  • Vue首屏性能优化组件知识点总结

    Vue首屏性能优化组件 简单实现一个Vue首屏性能优化组件,现代化浏览器提供了很多新接口,在不考虑IE兼容性的情况下,这些接口可以很大程度上减少编写代码的工作量以及做一些性能优化方面的事情,当然为了考虑IE我们也可以在封装组件的时候为其兜底,本文的首屏性能优化组件主要是使用IntersectionObserver以及requestIdleCallback两个接口. 描述 先考虑首屏场景,当做一个主要为展示用的首屏时,通常会加载较多的资源例如图片等,如果我们不想在用户打开时就加载所有资源,而是希望

  • 浅谈Vue 初始化性能优化

    前言 一般来说,你不需要太关心vue的运行时性能,它在运行时非常快,但付出的代价是初始化时相对较慢.在最近开发的一个Hybrid APP里,Android Webview初始化一个较重的vue页面竟然用了1200ms ~ 1400ms,这让我开始重视vue的初始化性能,并最终优化到200 ~ 300ms,这篇文章分享我的优化思路. 性能瓶颈在哪里? 先看一下常见的vue写法:在html里放一个app组件,app组件里又引用了其他的子组件,形成一棵以app为根节点的组件树. <body> <

  • Vue.js 无限滚动列表性能优化方案

    问题 大家都知道,Web 页面修改 DOM 是开销较大的操作,相比其他操作要慢很多.这是为什么呢?因为每次 DOM 修改,浏览器往往需要重新计算元素布局,再重新渲染.也就是所谓的重排(reflow)和重绘(repaint).尤其是在页面包含大量元素和复杂布局的情况下,性能会受到影响.那对用户有什么实际的影响呢? 一个常见的场景是大数据量的列表渲染.通常表现为可无限滚动的无序列表或者表格,当数据很多时,页面会出现明显的滚动卡顿,严重影响了用户体验.怎么解决呢? 解决方案 既然问题的根源是 DOM

  • Vue性能优化的方法

    今天来谈一谈Vue中一些性能优化的问题,仅仅是个人使用中的一些小心得,来,今天我一句废话不多说,直接上内容好吧 1.v-if和v-show的使用, 我们都知道这两个都可以控制显隐,那我们用哪个呢,个人觉得要从两个方面入手来确定使用哪个, 1.权限的问题,只要涉及到权限相关的展示用v-if比较好 2.切换地频率,如果频繁的切换我们用v-show,不频繁的切换用v-if 其实两者各有优缺,就看你是怎么选择了,用v-if能减少页面中的DOM总数,加快渲染的速度,而且我们要清楚一个事情 v-if是'真正

  • Vue中的性能优化方案

    目录 减少响应式使用 1. 使用 computed 缓存计算结果 2. 本地化响应式变量 3. 函数式组件(Vue2) 减少 DOM 渲染压力 1. DOM 频繁切换展示的情况使用 v-show 2. keep-alive 缓存组件状态 3. 路由懒加载 4. 图片懒加载 5. 组件销毁时要清除定时器.EventListener 6. 列表使用唯一 key 减少打包体积 1. 开启 gzip 压缩 2. 按需引入第三方组件 最近使用 Vue 开发的过程中使用到一些对于性能有所提升的编码方式,所以

  • Mysql性能优化方案分享

    网上有不少mysql 性能优化方案,不过,mysql的优化同sql server相比,更为麻烦,同样的设置,在不同的环境下 ,由于内存,访问量,读写频率,数据差异等等情况,可能会出现不同的结果,因此简单地根据某个给出方案来配置mysql是行不通的,最好能使用status信息对mysql进行具体的优化. mysql> show global status; 可以列出MySQL服务器运行各种状态值,另外,查询MySQL服务器配置信息语句: mysql> show variables; 一.慢查询

  • Vue清除定时器setInterval优化方案分享

    两种方案清除定时器,开发者经常使用方案1,建议使用方案2 方案1 首先我在data函数里面进行定义定时器名称: data() { return { timer: null // 定时器名称 } }, 然后这样使用定时器: this.timer = (() => { // 某些操作 }, 1000) 最后在beforeDestroy()生命周期内清除定时器: beforeDestroy() { clearInterval(this.timer); this.timer = null; } 方案1有

  • Vue项目打包编译优化方案

    1. 不生成.map文件 默认情况下,当我们执行 npm run build 命令打包完一个项目后,会得到一个dist目录,里面有一个js目录,存放了该项目编译后的所有js文件. 我们发现每个js文件都有一个相应的 .map 文件,它们仅是用来调试代码的,可以加快打包速度,但会增大打包体积,线上我们是不需要这个代码的.这里我们需要配置不生成map文件. vue-cli2 config/index.js文件中,找到 productionSourceMap: true 这一行,将 true 改为 f

  • Vue SPA 首屏优化方案

    前言 常规 vue 项目打包后访问,返回一个只包含 div 的 html,其他内容块都是通过 js 动态生成的. 存在两个比较大的问题: 不利于 seo 首屏加载页慢,用户体验不好 本文是自己根据项目经验总结的方案,如有不足,欢迎指出~ 优化 SSR SSR(Server-Side Rendering) 即服务端渲染,把 vue 组件在服务器端渲染为组装好的 HTML 字符串,然后将它们直接发送到浏览器,最后需要将这些静态标记混合在客户端上完全可交互的应用程序. 使用 ssr 重新部署构建项目后

  • Android性能优化方案详情

    目录 1.指标 2.包大小优化 3.响应时间优化 4.内存优化 5.CPU优化 6.耗电量优化 前言: 上一个季度在百度工作挺忙碌,在最后期限完成了OKR目标,因此有一段时间没有写文章.今天趁有机会想分享下在大型Android项目工程内的一些性能优化方式. 1.指标 量化性能的指标有很多,但最重要的就是以下5种: 包大小 响应时间 内存 CPU 耗电量 优化性能就是可以从以上5点入手. 2.包大小优化 顾名思义就是减少apk包体积大小,apk大小主要取决于res下的资源文件..class文件,

  • Vue.js 应用性能优化分析+解决方案

    目录 一.介绍 二.为什么我们需要 Vue JS 性能优化? 三.Vue 性能不佳背后的主要原因 1. 生成报告 2. 运行命令和npm 运行生成 四.如何优化 Vue js 应用程序的性能? 1. 在 Vue js 中懒加载 2. 基于路线的代码拆分 3.Vue js预加载组件 4. 优化第三方库 5. 使用浏览器缓存 6. 优化和压缩图像 前言: 假设我们在开发整个 Vue 应用程序方面非常努力.js.但没有优先考虑其性能:现在,我们的应用程序需要一段时间来加载.导航.提交或执行任何用户操作

随机推荐