Vue性能优化:从加载提速到运行时优化

前言

  • 常网IT源码上线啦!
  • 本篇录入吊打面试官专栏,希望能祝君拿下Offer一臂之力,各位看官感兴趣可移步🚶。
  • 有人说面试造火箭,进去拧螺丝;其实个人觉得问的问题是项目中涉及的点 || 热门的技术栈都是很好的面试体验,不要是旁门左道冷门的知识,实际上并不会用到的。
  • 接下来想分享一些自己在项目中遇到的技术选型以及问题场景。

真正的贵人,不会给你鱼,甚至都不一定会教你钓鱼,但一定会告诉你"什么是大海"。

一、前言

性能优化看哪些?

页面加载性能

核心指标:LCP(最大内容绘制)<2.5s,FID(首次输入延迟)<100ms

常见的场景:首屏内容可见时间

更新性能

核心指标:用户操作响应速度、视图更新效率

常见的场景:搜索过滤、SPA页面切换、数据驱动UI更新

有哪些工具可以分析分析。

工具类型 推荐工具 核心功能
生产环境分析 PageSpeed Insights 真实用户性能指标分析
WebPageTest 多地点/设备模拟测试
开发阶段分析 Chrome DevTools Performance 时间线性能分析
Vue专项工具 Vue DevTools 组件渲染追踪
app.config.performance = true 启用Vue专属性能标记

架构选型策略

包体积压缩三剑客

  • Tree-shaking​ ​:确保使用ES模块(如lodash-es替代lodash

  • ​模板预编译​​:避免运行时编译(节省14kb+)

  • ​依赖分析​​:使用bundlejs.com评估新增依赖成本

代码分割

代码分割是指构建工具将构建后的 JavaScript 包拆分为多个较小的,可以按需或并行加载的文件。

java 复制代码
// 路由级分割
const UserProfile = () => import('./UserProfile.vue')

// 组件级分割
const HeavyChart = defineAsyncComponent(
  () => import('./HeavyChart.vue')
)

可达到按需加载,避免首次加载太多组件(帮助应用暂时略过了那些不是立即需要的功能)

二、运行时更新优化

Props稳定性模式

这个技巧的核心思想就是让传给子组件的 props 尽量保持稳定。

java 复制代码
// 反模式:activeId变化导致所有列表项更新
<ListItem v-for="item in list" :active-id="activeId" />

// 优化:保持prop稳定
<ListItem 
  v-for="item in list"
  :active="item.id === activeId"  // 布尔值更稳定
/>

渲染指令优化

善用v-once和v-memo优化。

java 复制代码
<!-- v-once:静态内容冻结 -->
<Footer v-once />

<!-- v-memo:复杂列表优化 -->
<div 
  v-for="item in hugeList"
  :key="item.id"
  v-memo="[item.id, item.status]"
>
  <!-- 复杂子组件 -->
</div>

不可变数据优化

java 复制代码
// 大型数据使用浅层响应
const bigData = shallowRef({ ... })

// 修改时整体替换
bigData.value = { ...bigData.value, key: newValue }

计算属性高级技巧

java 复制代码
// 避免返回新对象
const userInfo = computed(() => ({
  name: user.value.name,
  isVIP: user.value.level > 3
}))

// 手动优化:值相同时返回旧引用
const optimizedInfo = computed((oldValue) => {
  const newValue = { /* 计算逻辑 */ }
  return isEqual(newValue, oldValue) ? oldValue : newValue
})

watch的优化:

java 复制代码
// 避免深度监听大型对象
watch(
  () => largeObj.value.id,  // 只监听必要属性
  (newId) => { ... }
)

// 高频操作使用防抖
watch(
  searchInput, 
  debounce((val) => fetchData(val), 300)
)

避免深层侦听

java 复制代码
watch( 
    () => state.list, 
    (newList) => {
        // 处理列表变化
    }, 
    { deep: false }
    // 明确禁用深层侦听 
)

高效的事件侦听器

java 复制代码
const stop = watchEffect((onCleanup) => {
  const timer = setTimeout(doWork, 100)
  
  // 清理函数优化
  onCleanup(() => {
    clearTimeout(timer)
    cleanupResources()
  })
})

大型列表

不管一个框架做得再好,一旦遇到大型列表的渲染,必定很慢很卡,这很正常,因为浏览器要渲染这么多的DOM。

但我们可以优化成:只渲染可视区的列表,然后随着滚动慢慢加载替换上来可视区内。

滚动节流:使用 requestAnimationFrame 优化滚动处理

占位符优化:使用骨架屏替代空白区域

动态加载:根据滚动速度预测加载范围

推荐库:

  • 通用列表:vue-virtual-scroller

  • 网格布局:vue-virtual-scroll-grid

优化禁忌:​

  • 避免在大型列表中使用深度响应式

  • 谨慎使用 v-html(可能绕过编译优化)

  • 避免在模板中使用复杂表达式

​渐进优化策略

java 复制代码
// 初始实现
const state = reactive({ bigData: [...] })

// 阶段1:浅层响应
const state = shallowReactive({ bigData: [...] })

// 阶段2:虚拟化展示
<VirtualList :items="state.bigData" />

// 阶段3:按需加载
const visibleData = computed(() => 
  state.bigData.slice(virtualStart.value, virtualEnd.value)
)

三、组件设计

层级不要嵌套太多层,如果用循环,更需要注意这点。

java 复制代码
// 谨慎使用抽象组件
// 在1000项列表中:
<template v-for="item in list">
  <!-- 反模式:每项增加1层抽象 -->
  <AbstractWrapper> 
    <ListItem />
  </AbstractWrapper>
  
  <!-- 优化:直接渲染 -->
  <ListItem />
</template>

每个组件实例消耗≈普通DOM节点的10倍内存。

无渲染组件优化

传统无渲染组件

java 复制代码
<RenderlessList :items="items" v-slot="{ item }"> 
    <ListItem :item="item" /> 
</RenderlessList>

优化后:直接使用组合式函数

java 复制代码
<script setup>
  import { useList } from './useList'
  
  const { processedItems } = useList(props.items)
</script>

<template>
  <ListItem
      v-for="item in processedItems"
      :key="item.id"
      :item="item"
  /> 
</template>

至此撒花~

后记

还是想说:避免过度优化,还是要以真实场景决策!

我们在实际项目中或多或少遇到一些奇奇怪怪的问题。

自己也会对一些写法的思考,为什么不行🤔,又为什么行了?

最后,祝君能拿下满意的offer。

我是Dignity_呱,来交个朋友呀,有朋自远方来,不亦乐乎呀!深夜末班车

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

vue2和Vue3和React的diff算法展开说说:从原理到优化策略

玩转Vue插槽:从基础到高级应用场景(内含为何Vue 2 不支持多根节点)

前端哪有什么设计模式(14k+)

小小导出,我大前端足矣!

前端仔,快把dist部署到Nginx上

多图详解,一次性啃懂原型链(上万字)

Vue-Cli3搭建组件库

Vue实现动态路由(和面试官吹项目亮点)

VuePress搭建项目组件文档

原文链接

juejin.cn/post/751197...

相关推荐
问心无愧05131 分钟前
ctf show web入门261
android·前端·笔记
触底反弹3 分钟前
你真的理解 JavaScript 变量提升(Hoisting)吗?从 V8 引擎编译原理深入剖析
前端·面试
蜡台15 分钟前
Vue2 使用 typescript 教程
前端·vue.js·typescript
光影少年28 分钟前
Redux Toolkit 用法、解决原生Redux 冗余问题
开发语言·前端·javascript·react.js·中间件·前端框架·ecmascript
云水一下35 分钟前
JavaScript 从零基础到精通系列:DOM 操作与事件驱动编程
前端·javascript
努力发光的程序员1 小时前
面试官与程序员谢飞机的3轮Java大厂面试问答实录:涵盖Spring Boot、微服务与数据库技术
java·jvm·spring boot·redis·面试·hibernate·microservices
ZC跨境爬虫1 小时前
跟着 MDN 学CSS day_32:(Web字体深度解析与实践指南)
前端·javascript·css·ui·html
Rick19931 小时前
Redis 高频面试 10 题
数据库·redis·面试
砍材农夫1 小时前
物联网 基于netty核心实战-安全tls
java·开发语言·前端·物联网·安全