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...

相关推荐
然我5 分钟前
别再只用 base64!HTML5 的 Blob 才是二进制处理的王者,面试常考
前端·面试·html
NanLing7 分钟前
【纯前端推理】纯端侧 AI 对象检测:用浏览器就能跑的深度学习模型
前端
呆呆的心9 分钟前
前端必学:从盒模型到定位,一篇搞定页面布局核心 🧩
前端·css
小飞悟9 分钟前
前端高手才知道的秘密:Blob 居然这么强大!
前端·javascript·html
小old弟10 分钟前
用Sass循环实现炫彩文字跑马灯效果
前端
code_YuJun10 分钟前
Promise 基础使用
前端·javascript·promise
Codebee10 分钟前
OneCode自主UI设计体系:架构解析与核心实现
前端·javascript·前端框架
GIS之路13 分钟前
GIS 空间关系:九交模型
前端
xiguolangzi20 分钟前
vue3+element-plus el-table列的显隐、列宽 持久化
前端·javascript·vue.js
用户68238060322522 分钟前
前端会用到的数据结构--堆(HEAP)
前端