Skip to content

Vue2 常见优化手段

使用 key

通过循环生成的列表,应该给每个列表项一个稳定且唯一的值作为 key,这利于在列表变动时,尽量少的删除、新增、改动元素。

示例:

vue
<template>
  <ul>
    <!-- 使用 id 而不是 index 作为 key -->
    <li v-for="(item, index) in items" :key="item.id">
      {{ item.name }}
    </li>
  </ul>
</template>

使用冻结对象

对于一些不会变动的数据,使用 Object.freeze(obj) 冻结对象,它不会被"响应化"。

示例:

vue
<script>
const obj = { name: '张三' }
Object.seal(obj)

export default {
  data: {
    myObj: obj,
  },
}
</script>

使用函数式组件

👉 函数式组件

提升虽然比较小,但是仍然有提升:

  1. 渲染时间减少。
  2. 减少内存消耗:普通组件会创建一个组件实例,而函数式组件不会创建实例。

使用计算属性

如果模板中某个数据会使用多次,并且该对象是通过计算得到的,使用计算属性 缓存 它,

非实时地绑定表单项

当使用 v-model 绑定一个表单项时,当用户改变表单项的状态时,它会随之改变数据,从而导致 vue 发生重新渲染(rerender),这会带来一些性能开销。

可以通过使用 lazy 或不使用 v-model 的方式解决该问题,但要注意的是,这样可能会导致在某一个时间段内数据和表单项的值是不一致的!

保持对象引用稳定

在绝大部分情况下,vue 触发 rerender 的时机是其依赖的数据发生变化。

若数据没有发生变化,哪怕是给数据重新赋值了,vue 也是不会做出任何处理的。

参考 vue 源码(判断数据没有变化):

js
function hasChanged(x, y) {
  if (x === y) {
    return x !== 0 || 1 / x === 1 / y
  } else {
    return x === x || y === y
  }
}

因此,如果需要,只要能保证组件的依赖数据不发生变化,组件就不会重新渲染:

  • 对于原始类型,保持其值不变即可。
  • 对于引用类型,保持其引用不变即可。

使用 v-show 代替 v-if

对于频繁切换显示状态的元素,使用 v-show 可以保证虚拟 dom 树的稳定,避免频繁地新增和删除元素,特别是对于哪些内部包含大量 dom 元素的节点!

使用 v-show 的关键点:

  1. 频繁切换显示状态。
  2. 内部包含大量 dom 元素。

延迟装载(defer)

JS 传输完成后,浏览器会开始执行 JS 构造页面。

但是可能一开始要渲染的组件太多了,不仅 JS 执行的时间长,而且执行完后浏览器要渲染的元素过多,从而导致页面白屏。

一个可行的方法就是 延迟装载组件,让组件按照指定的先后顺序依次一个一个地渲染出来。

提示

延迟状态是一个思路,本质就是利用了 requestAnimationFrame 事件分批渲染内容,它的具体实现是多种多样的。

例如:

vue
<template>
  <div>
    <child-component v-for="(item, index) in loadedComponents" :key="index" :name="item" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
  components: { ChildComponent },
  data() {
    return {
      loadedComponents: [], // 已渲染的组件
      components: ['A', 'B', 'C', 'D', 'E'], // 需要渲染的组件
    }
  },
  methods: {
    renderNext(index) {
      if (index >= this.components.length) return
      requestAnimationFrame(() => {
        this.loadedComponents.push(this.components[index]) // 逐个添加组件
        this.renderNext(index + 1) // 递归渲染下一个组件
      })
    },
  },
  mounted() {
    this.renderNext(0)
  },
}
</script>

使用 keep-alive

keep-alive 主要用于 优化性能,避免组件频繁销毁和创建。

长列表优化

当一个列表数据量很大(如 1 万条数据)时,直接渲染所有数据会导致严重的性能问题:

  1. DOM 节点过多,导致浏览器渲染变慢
  2. 内存占用过高,页面变卡顿
  3. 滚动体验变差

解决方案就是 虚拟列表,它只渲染可视区域的数据,而不是整个列表。

虚拟列表的核心思想是:

  • 可见区域渲染:只渲染视口内的少量 DOM 节点,未滚动到的部分不渲染。
  • 占位填充:用 padding 或 transform: translateY() 来模拟完整高度,让滚动条正常工作。
  • 滚动更新:监听 scroll 事件,动态更新可见数据。

可以自己实现虚拟列表组件,或者使用第三方库 vue-virtual-scroller

优化打包体积

参考工程化,如:webpack、vite、rollup 等。

基于 MIT 许可发布