news 2026/6/24 4:52:51

性能优化 - Vue 日常实践优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
性能优化 - Vue 日常实践优化

在 Vue 应用开发过程中,通过合理使用框架特性、避免性能陷阱、优化组件设计等方式,从代码层面提升应用性能。

优化实践

使用内置 API 完成需求

JIT 是浏览器中的 JavaScript 引擎在运行时,把热点 JavaScript 代码即时编译为机器码,从而提高执行性能的一种机制。

Chrome 浏览器 JIT 指内置的 JavaScript 引擎 V8 的即时编译机制。

使用 DOM API / BOM API / Vue API 完成开发,DOM API / BOM API / Vue API 通常有对应的优化算法,必要时或节约开发成本时再使用第三方工具类库辅助。

  • API 底层都是基于 V8 引擎,相比 JS 层 JIT 编译执行而言,基于 C++ 的 V8 会更快。
  • sort会根据情况采用归并或者插入排序(小数组采用插入,大数组采用归并或者是归并 + 插入的混合排序方案),相比手动实现的 JS 排序功能更优。
  • 遍历时使用for...of/for代替for...infor...in语义需要收集对象自身的枚举属性,然后再去遍历原型链上的属性,过滤掉不可枚举的属性值,然后处理属性遮蔽问题,最终动态决定遍历结果,这个无法预测的枚举流程是无法被跳过的,在数组遍历时只能执行慢路径查找。
// 推荐:使用 for...of 或 for 循环constarr=[1,2,3,4,5];for(constitemofarr){console.log(item);}// 或使用传统 for 循环for(leti=0;i<arr.length;i++){console.log(arr[i]);}// 避免:使用 for...in 遍历数组(性能较差)for(constindexinarr){console.log(arr[index]);}

避免非必要响应式

避免将非响应式实例声明为响应式,尤其注意不要将插件实例声明为响应式,在 Vue2 中会由于深度递归响应,导致大量内存被占用,严重会出现假死的情况。
在 Vue3 中,可以使用shallowRefshallowReactive来避免非必要的响应逻辑。

// ❌ 将插件实例声明为响应式exportdefault{data(){return{// Vue2 会深度递归处理,导致性能问题echart:null,moment:moment,};},mounted(){this.echart=echart.init();}};// ✅ 使用 Object.freeze 或直接挂载到 thisexportdefault{data(){return{// 使用 Object.freeze 冻结对象,避免响应式处理// Vue 处理响应式之前会去判断 configurable 描述符是否可用,不可用不会进行响应式处理axios:Object.freeze(axios),};},created(){// 或直接挂载到实例上,不放入 datathis.axios=axios;},};

Keepalive 缓存

使用<keep-alive>缓存组件,根据需求进行缓存,小型项目可以直接进行RouterView级别缓存,大型项目指定对大型组件的缓存,同时通过max指定最大缓存组件数,注意要在activateddeactivated中完成组件的唤醒和卸载处理。

<!-- 小型项目:RouterView 级别缓存 --><template><keep-alive:max="10"><router-view/></keep-alive></template><!-- 大型项目:指定组件缓存 --><template><keep-alive:include="['ComponentA','ComponentB']":max="5"><component:is="currentComponent"/></keep-alive></template><script>exportdefault{name:"ComponentA",activated(){// 组件被激活时执行// 完成定时器、事件、数据请求this.setTimers();this.refreshData();},deactivated(){// 组件被停用时执行// 销毁定时器,事件,避免内存泄漏和逻辑冲突this.clearTimers();},};</script>

v-if 和 v-show

频繁切换避免使用v-if,使用v-show,由于v-show会导致代码不太美观,可以的话通过<component :is="bindComponent">或者v-if结合<keep-alive>实现类似的逻辑。

<template><!-- ❌ v-if 会销毁和重建组件 --><divv-if="showComponent">组件内容</div><!-- ✅ v-show 只切换 display 样式 --><divv-show="showComponent">组件内容</div><!-- ✅ 使用 component 动态组件 + keep-alive 组合,保持代码美观,配合异步组件优化首次渲染体积,基于 keep-alive 实现异步组件缓存策略 --><keep-alive><component:is="currentComponent"/></keep-alive></template><script>exportdefault{components:{// Vue3 用 defineAsyncComponent 封装引入ComponentA:()=>import("./components/componentA"),ComponentB:()=>import("./components/componentB"),},data(){return{showComponent:true,currentComponent:"ComponentA",};},};</script>

Computed 缓存

计算内容可以用computed计算属性去缓存,computed会在依赖属性更新触发视图更新时,才会根据dirty标志位判断依赖属性是否更新,决定计算新值还是获取缓存值。

<template><div><p>总价:{{ totalPrice }}</p><p>折扣价:{{ discountPrice }}</p></div></template><script>exportdefault{data(){return{items:[{price:10,quantity:2},{price:20,quantity:3},],discount:0.8,};},computed:{// ✅ 依赖变化时才重新计算,否则使用缓存totalPrice(){returnthis.items.reduce((sum,item)=>sum+item.price*item.quantity,0);},// 依赖 totalPrice 计算结果,totalPrice 缓存时 discount 不会重复计算discountPrice(){returnthis.totalPrice*this.discount;},},// ❌ 不推荐:使用 methods 每次都会重新计算methods:{getTotalPrice(){returnthis.items.reduce((sum,item)=>sum+item.price*item.quantity,0);},},};</script>

内部创建和销毁

销毁监听器、定时器、实例,避免出现内存泄漏影响性能问题。

<script>exportdefault{data(){return{timer:null,resizeHandler:null,};},mounted(){// 创建定时器this.timer=setInterval(()=>{console.log("定时任务");},1000);// 小技巧:通过 AbortController 可以同时销毁多个事件监听器this.controller=newAbortController();window.addEventListener("scroll",this.scrollHandler,{signal:this.controller.signal,});window.addEventListener("resize",this.resizeHandler,{signal:this.controller.signal,});// 三方插件初始化this.thirdPlugin=plugin.init();},methods:{resizeHandler(){// resize 事件},scrollHandler(){// scroll 事件},},beforeDestroy(){// ✅ 销毁定时器if(this.timer){clearInterval(this.timer);this.timer=null;}// ✅ 销毁事件监听if(this.controller){this.controller.abort();this.controller=null;}// ✅ 销毁插件实例if(this.thirdPlugin){// 先看三方插件内部是否有销毁 API 主动执行,避免插件内部引用未销毁导致泄漏this.thirdPlugin.destroy();this.thirdPlugin=null;}},};</script>

异步组件

Vue-Router 和 Vue 通过异步组件方式按需引入,必要时再进行加载。

但是要避免过度拆分,当组件拆分前请求成本(请求耗时、请求体积、是否重复) > 组件拆分后的请求成本时,再考虑进行拆分。

importHomefrom"@/views/Home.vue";// Vue Router 异步组件constroutes=[{path:"/home",// 首页不推荐异步逻辑,避免首页加载白屏component:Home,},{path:"/large-page",// ✅ 使用 webpackChunkName 指定 chunk 名称,避免过渡拆包,可以把同个页面下的子路由都集中在webpackChunk中加载,也可以按需拆分component:()=>import(/* webpackChunkName: "large-page" */"@/views/LargePage.vue"),},];// Vue 组件异步加载exportdefault{components:{// ✅ 异步组件:按需加载HeavyComponent:()=>import("@/components/HeavyComponent.vue"),// ✅ 带加载状态和错误处理, Vue3 使用 defineComponent APIAsyncComponent:()=>({component:import("@/components/AsyncComponent.vue"),loading:LoadingComponent,error:ErrorComponent,delay:200,// 延迟显示 loadingtimeout:3000,// 超时时间}),},};

Vue 官方优化实践

  • Vue.js 官方文档 - 性能优化:提供关于 v-once 和函数式组件的优化方案等。
  • Vue2 Cookbook:关于 Vue2 的最佳实践。

总结

  • 使用内置 API:优先使用 DOM API / BOM API / Vue API 完成开发,这些 API 基于 V8 引擎优化,性能优于手动实现的 JavaScript 代码。遍历时使用for...of/for代替for...in,避免慢路径查找。
  • 避免非必要响应式:避免将插件实例等非响应式对象声明为响应式,在 Vue2 中会由于深度递归响应导致性能问题。使用Object.freeze冻结对象或直接挂载到实例上,避免响应式处理。
  • 组件缓存:使用<keep-alive>缓存组件,小型项目可以直接进行RouterView级别缓存,大型项目指定对大型组件的缓存,同时通过max指定最大缓存组件数。注意要在activateddeactivated中完成组件的唤醒和卸载处理。
  • 条件渲染优化:频繁切换避免使用v-if,使用v-show。可以通过<component :is="bindComponent">或者v-if结合<keep-alive>实现类似的逻辑,保持代码美观的同时优化性能。
  • 计算属性缓存:使用computed计算属性缓存计算结果,computed会在依赖属性更新触发视图更新时,根据dirty标志位判断是否重新计算,否则使用缓存值。
  • 资源清理:及时销毁监听器、定时器、实例,避免内存泄漏。可以使用AbortController同时销毁多个事件监听器,对于三方插件需要主动调用销毁 API。
  • 异步组件:通过异步组件方式按需引入,优化首屏加载速度。但要避免过度拆分,需要权衡组件拆分前后的请求成本(请求耗时、请求体积、是否重复)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/16 14:34:46

RaNER模型推理慢?AI智能实体侦测服务CPU加速部署方案

RaNER模型推理慢&#xff1f;AI智能实体侦测服务CPU加速部署方案 1. 背景与痛点&#xff1a;中文NER的性能挑战 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;命名实体识别&#xff08;Named Entity Recognition, NER&#xff09;是信息抽取的核心任务之一。尤…

作者头像 李华
网站建设 2026/6/16 14:34:44

15分钟用QT5打造物联网设备控制面板原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 快速生成一个QT5物联网设备控制面板原型&#xff1a;1) 模拟控制3个智能灯泡&#xff1b;2) 每个灯泡有开关按钮和亮度滑块&#xff1b;3) 显示当前环境温湿度数据&#xff1b;4) …

作者头像 李华
网站建设 2026/6/21 22:00:31

1小时验证创意:用数据流图快速构建系统原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个快速原型工具&#xff1a;输入商业想法自动生成可能的数据流图架构。功能&#xff1a;1. 识别核心业务实体 2. 推断典型数据交互 3. 生成可交互的简化流程图 4. 支持多人协…

作者头像 李华
网站建设 2026/6/14 0:18:17

中文NER服务案例解析:RaNER模型在法律文书中的应用

中文NER服务案例解析&#xff1a;RaNER模型在法律文书中的应用 1. 引言&#xff1a;AI 智能实体侦测服务的现实需求 在司法、金融、政务等高信息密度领域&#xff0c;非结构化文本中蕴含着大量关键实体信息——如涉案人员姓名、相关机构、地理位置、时间与金额等。传统人工提…

作者头像 李华
网站建设 2026/6/19 15:32:29

企业级SQL2016集群安装实战指南

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 生成一个分步骤的SQL Server 2016故障转移集群部署方案&#xff0c;包含&#xff1a;1) 共享存储配置要求 2) 网络负载均衡设置 3) 集群验证报告解读 4) 安装后的故障转移测试步骤…

作者头像 李华
网站建设 2026/6/21 4:28:46

Qwen2.5-7B私有化部署避坑指南:云端GPU省去80%成本

Qwen2.5-7B私有化部署避坑指南&#xff1a;云端GPU省去80%成本 引言&#xff1a;初创公司的AI落地困境 作为初创公司CTO&#xff0c;你可能正在评估是否要用Qwen2.5-7B替代现有付费API。但一算账就头疼&#xff1a;买张A100显卡要15万&#xff0c;云厂商包月报价8000&#xf…

作者头像 李华