一些Vue的性能优化

代码优化

  1. 模块化、组件化
  • 组件是把常用的东西封装起来,最重要的就是复用。
  • 模块是把同一功能或业务的代码进行分离,降低模块间的耦合性,可以独立运行和管理。
  • 包括css也可以通过less和sass来减少重复代码。
  1. v-for 的 key
    在使用v-for渲染元素列表时,为每一项都设置唯一的key值,为了让Vue内部更快的定位到该条数据。
    我们都知道尽量不要使用index下标作为key值,例如:
let arr = [
   { id: 1, title: 'one' },
   { id: 2, title: 'two' },
   { id: 3, title: 'three' }
]
arr.splice(1, 1)
console.log(arr)

这时index发生了变化,列表中所有的key值都发生了变化,此时v-for会对key变化的元素重新渲染,但其实除了删除的元素其他都没有发生变化,导致vue用错误的旧子节点,做很多没有必要的工作。所以尽量不要使用index作key值,使用id等字段更好,也不要用随机数作为key,删掉旧节点,创建新节点,你的老板会被气死。

  1. v-for 和 v-If
    官方都告诉我们啦,当和v-if一起使用时,v-for的优先级更高,显然每一次渲染列表时都需要进行一次判断,更好的办法是用computed将不需要的值过滤掉。
    还想多巴巴一句的是,v-if是对销毁和重建DOM进行元素的显示和隐藏,有更高的切换消耗,而v-show是通过display的简单操作,初始渲染消耗更高,频繁切换DOM时适用。(发现自己大部分项目都是直接用v-if的)
  2. 懒加载
    4.1 路由懒加载
    可以加快首屏渲染的速度。
 {
  path: "/tips",
  name: "tips",
  component: resolve => require(["@/views/tips"], resolve),
  meta: {
    title: "路由懒加载"
  }
}

关于首屏优化,过大的项目可能会因为没有加载完出现白屏的情况,可以加个loading加载提示或者启动页。
4.2 图片懒加载

  • 大多数框架都有图片懒加载的功能,多多使用。
  • 使用Base64加载小图片
  • 图标尽可能使用svg和字体图标
  1. keep-alive缓存
    keep-alive是用来缓存组件从而节省性能的抽象组件,被包裹在keep-alive中的组件其状态会被保留,避免重新渲染。
<!--`` 一起使用 -->
<transition>
 <keep-alive>
   <component :is="view"></component>
 </keep-alive>
</transition>

利用include、exclude属性,二者都可以用逗号分隔字符串、正则表达式或一个数组来表示。
include属性表示只有name属性为a,b的组件会被缓存,其它组件不会被缓存,exclude属性表示除了name属性为c的组件不会被缓存,其它组件都会被缓存。

<!-- 注意是组件的名字,不是路由的名字 -->
<keep-alive include="a,b">
      <router-view></router-view>
</keep-alive>
<keep-alive exclude="c">
      <router-view></router-view>
</keep-alive>
  1. 钩子hook
    (1) 同一个组件中
mounted() {
 // 在Vue组件中,可以用$on,$once去监听所有的生命周期钩子函数
 // 可以通过hook监听组件销毁钩子函数,并取消监听事件
 this.$once("hook:beforeDestroy", () => {
   // 官方建议我们 私有property名 以$_开头
   window.removeEventListener("resize", this.$_handleListen);
 });
},

(2) 父子组件中

<!-- 组件的所有生命周期钩子都可以通过@hook:钩子函数名 来监听触发 -->
<component @hook:updated="$_handleListen" />

平时大多数功能不需要hook也能实现,但当第三方组件库还没有实现@change回调时,hook真的是贼香了!

  1. Object.freeze()
    如果你有一个超大的Array或Object,并且确信数据不会修改,使用Object.freeze()可以让性能大幅提升。
<!-- 组件的所有生命周期钩
mounted() {
  let arr = [1, 2, 3, 4, 5]
  Object.freeze(arr)
}

当数据是滚动加载时,也是可以用concat添加数据的,合理地使用Object.freeze()可以节省很多渲染性能。

  1. watch监听
    比如一个列表页,我们希望用户在搜索框输入搜索关键字的时候,可以自动触发搜索,可以通过watch监听搜索关键字的变化。
data() {
  return {
    serachValue: ''
  };
},
watch: {
  // 在值发生变化之后,重新加载数据
  searchValue: {
    // 通过handler来监听属性变化, 初次调用 newValue为""空字符串, oldValue为 undefined
    handler(newValue, oldValue) {
      if (newValue !== oldValue) {
        console.log('做了一些事');
      }
    },
    // 立即触发  如需要初始化加载数据
    immediate: true,
    // 深度监听  指定deep属性为true, watch会监听对象里面每一个值的变化
    deep: true
  }
},
  1. 函数式组件
    纯展示性的业务组件,只需要将外部传入的数据进行展现,不需要有内部状态,不需要在生命周期钩子函数里面做处理,这时候就可以考虑使用函数式组件。
// 由于函数式组件没有创建组件实例,所有传统的通过this来调用的属性,在这里都需要通过context来调用
Vue.component('my-functional-button', {
  functional: true,
  render: function (createElement, context) {
    return createElement('button', context.data, context.children)
  }
})

项目优化

  1. 按需引入
    使用UI框架尽量按需引入,减少多余的开销,合理的及时止损。

  2. 使用cdn的方式外部加载一些资源

  • 不必要打包的外部引用模块可以通过cdn引入。
  • 还有一些通过cdn加速的大图
  1. vue.config.js配置
    如果不设置打包会生成一些map文件,生产环境可以通过map去查看源码。
module.exports = {
    productionSourceMap: false,
}

官方config参考文档

  1. 删除多余的代码,减少图片的使用
  • 删除一些注释和打印的代码…
  • 图片会占很大一部分体积,一些图片效果可以通过css3来实现…

你可能感兴趣的:(一些Vue的性能优化)