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

相关推荐
lexiangqicheng28 分钟前
es6+和css3新增的特性有哪些
前端·es6·css3
拉不动的猪1 小时前
都25年啦,还有谁分不清双向绑定原理,响应式原理、v-model实现原理
前端·javascript·vue.js
烛阴1 小时前
Python枚举类Enum超详细入门与进阶全攻略
前端·python
孟孟~1 小时前
npm run dev 报错:Error: error:0308010C:digital envelope routines::unsupported
前端·npm·node.js
孟孟~2 小时前
npm install 报错:npm error: ...node_modules\deasync npm error command failed
前端·npm·node.js
狂炫一碗大米饭2 小时前
一文打通TypeScript 泛型
前端·javascript·typescript
wh_xia_jun2 小时前
在 Spring Boot 中使用 JSP
java·前端·spring boot
二十雨辰2 小时前
[HTML5]快速掌握canvas
前端·html
tingkeiii3 小时前
【react+antd+vite】优雅的引入svg和阿里巴巴图标
前端·react.js·前端框架
清幽竹客3 小时前
vue-18(使用 Vuex 插件实现高级功能)
前端·vue.js·前端框架·vue