vue性能优化

文章目录

1.代码优化

2.项目优化

3.其它优化

4.总结

本文主要针对的是 vue 2.x 版本的性能优化,并且从代码优化 和 其他的优化去讲下在项目开发时应该注意的优化事项。

首先从项目代码层面方面

1.代码优化

v-if / v-show

这两个指令在不同场景的使用下,会有不同的性能损耗情况,首先简单了解下两者的区别。

  • v-if 指令在编译阶段就会编译成一个三元运算符,通过条件进行渲染。当条件的值变化时,会触发对应的组件更新,即会经过 diff 算法, 组件初始化、渲染 vnode、patch等过程。
  • v-show 指令相比于 v-if 的优势就是它在更新阶段仅仅更新了 DOM 的显隐,少去了很多性能开销的操作。但是初始化的时候会把所有条件节点都渲染出来





  • 使用场景:

初始化阶段: v-if 性能优于 v-show
频繁更新阶段: v-show 性能优于 v-if

v-for 和 v-if

避免把这两个指令放在同一个节点

因为 v-for 指令的优先级比 v-if 高,所以两个指令混用的话会导致每次节点render的结果都带上了条件渲染。当数据量和节点复杂的时候,就会有明显的性能差。

当我们要循环节点和条件判断的时候,我们可以先对数据进行处理后再进行 v-for 渲染,如下例子:


{{item.name}}
{{item.name}}
computed: { filters () { return this.list.filter(item => item.count > 10) } }

从上面例子不难看出,每个 v-for 节点处就加了 key 唯一标识,这也是提升性能的一个小点。使用 key 时,vue会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。

keep-alive

部分场景可以使用 keep-alive 进行组件缓存

keep-alive 包裹的组件在经过渲染后的 vnode 以及 DOM 都会被缓存起来,然后下次再次渲染该组件的时,直接从缓存中拿到对应的 vnode 和 DOM 并且进行渲染,并不需要再走一次组件初始化,render 和 patch 等一系列流程,减少了 script 的执行时间,性能更好。

v-slot:slotName / slot="slotName"

vue 2.6 版本,可以使用 v-slot:slotName 的语法代替 slot="slotName"

  • 旧的写法在更新时多了一个父组件更新的过程,而新的写法由于直接更新子组件,就会更加高效,性能更好,所以推荐始终使用语法 v-slot:slotName
函数式组件

vue 2.x 的版本,需要DOM层复用的情况且场景相对简单时,可以用 函数式组件 代替普通组件

函数式组件生成的是普通的 vnode,不会存在递归子组件的过程,所以会减少一定程度的性能开销

场景:我在多个页面都复用了一个页面渲染的组件,不需要一些复杂的操作,只需要根据传参进行条件渲染或者循环渲染等、就可以用如下的例子去进行组件的编写



子组件拆分

除开代码维护的层面,从性能方面,组件的拆分也是有好处的。

  • 因为vue 的更新是组件力度,如果组件中有数据发生变化,就会执行 render 函数生成新的 vnode 和旧的 vnode 进行 diff。哪怕这个数据只影响到一个元素渲染,其他元素也需要在 diff 过程中进行比较。极端情况是假设这个大组件里面有个倒计时。
  • 如果组件拆分得当的话,大部分的数据改动只会影响到子组件本身进行 diff ==> 渲染。所以合理得对这种大组件进行拆分,应用的更新效率会更高。

例如:











响应式数据优化
data的优化

vue 在组件实例初始化的时候会对data进行响应式处理,能够减少一个数据就是减少一点点的性能开销。而且一些常量数据不应该在data里面进行定义,简单总结为以下三点:

  • 减少无用的data数据

  • 减少数据被observer

  • 数据尽量扁平化

局部变量缓存响应式数据

先直接看对比代码

// 优化前
// ··········
computed: {
  base () {
    return 42
  },
    result () {
      let result = this.start
      for (let i = 0; i < 1000; i++) {
        result += Math.sqrt(Math.cos(Math.sin(this.base))) + this.base * this.base + this.base + this.base * 2 + this.base * 3
      }
      return result
    },
}

// 优化后
// ·········
computed: {
  base () {
    return 42
  },
    result ({ base, start }) {
      let result = start
      for (let i = 0; i < 1000; i++) {
        result += Math.sqrt(Math.cos(Math.sin(base))) + base * base + base + base * 2 + base * 3
      }
      return result
    },
}

优化前每次调用 this.base 的时候,由于它是个响应式数据,每次都会调用都会触发它的 getter,进而执行依赖收集等逻辑。

优化后先把 this.base 缓存到局部变量,后面重复调用的时候就不会频繁的触发到 getter 的逻辑处理

computed

计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 数据 还没有发生改变,多次访问 计算属性会立即返回之前的计算结果,可以极大提升性能。

例如:



2.项目优化

路由懒加载

在vue-router的配置文件里,定义一个能够被 Webpack 自动代码分割的异步组件

const Hello = () => import('//hello.vue')
const router = new VueRouter({
  routes: [
    { path: '/hello', component: Hello },
    { path: '/world', component: import('//world.vue') }
  ]
})
组件按需加载

element-ui 为例子,有些项目用ui组件库的时候使用的并不多,可以按需加载适当优化项目的体积

import {Button} from 'element-ui'

Vue.use(Button)

3.其它优化

1.图片懒加载
2.节流 / 防抖
3.长列表的虚拟滚动

4.总结

1.减少没必要的渲染机制
2.减少全量加载,适当的懒加载
3.正确的使用vue的每个api,本身vue这个框架就对性能方面做了很多处理,正常使用就不会出现性能瓶颈

你可能感兴趣的:(vue性能优化)