vue性能优化技巧

  1. Functional components
函数式组件和普通的对象类型的组件不同,它不会被看作成一个真正的组件,在 patch 组件 vnode,会递归执行子组件的初始化过程; 而函数式组件的 render 生成的是普通的 vnode,没有递归子组件的过程,因此渲染开销会低很多。

  1. Child component splitting
// 由于 Vue 的更新是组件粒度的,虽然每一帧都通过数据修改导致了父组件的重新渲染, //但是 ChildComp 却不会重新渲染,因为它的内部也没有任何响应式数据的变化。所以优化后的组件不会在每次渲染都执行耗时任务, //自然执行的 JavaScript 时间就变少了。 //实际情况下更多利用计算属性的缓存

  1. Local variables
// 由于 this.base 是一个响应式对象,所以会触发它的 getter, //进而会执行依赖收集相关逻辑代码。类似的逻辑执行多了,又多次执行依赖收集相关逻辑,性能自然就下降了。

  1. Reuse DOM with v-show
    v-if 渲染的节点,由于新旧节点 vnode 不一致,在核心 diff 算法比对过程中,会移除旧的 vnode 节点,创建新的 vnode 节点,那么就会创建新的 Heavy 组件,又会经历 Heavy 组件自身初始化、渲染 vnode、patch 等过程。
v-if
function render() { with(this) { return _c('div', { staticClass: "cell" }, [(props.value) ? _c('div', { staticClass: "on" }, [_c('Heavy', { attrs: { "n": 10000 } })], 1) : _c('section', { staticClass: "off" }, [_c('Heavy', { attrs: { "n": 10000 } })], 1)]) } }

v-show
function render() { with(this) { return _c('div', { staticClass: "cell" }, [_c('div', { directives: [{ name: "show", rawName: "v-show", value: (props.value), expression: "props.value" }], staticClass: "on" }, [_c('Heavy', { attrs: { "n": 10000 } })], 1), _c('section', { directives: [{ name: "show", rawName: "v-show", value: (!props.value), expression: "!props.value" }], staticClass: "off" }, [_c('Heavy', { attrs: { "n": 10000 } })], 1)]) } }

但是 v-show 相比于 v-if 的性能优势是在组件的更新阶段,如果仅仅是在初始化阶段,v-if 性能还要高于 v-show,原因是在于它仅仅会渲染一个分支,而 v-show 把两个分支都渲染了,通过 style.display 来控制对应 DOM 的显隐。
  1. KeepAlive

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

【vue性能优化技巧】优化后

Defer 的主要思想就是把一个组件的一次渲染拆成多次,它内部维护了 displayPriority 变量,然后在通过 requestAnimationFrame 在每一帧渲染的时候自增,最多加到 count。然后使用 Defer mixin 的组件内部就可以通过 v-if="defer(xxx)" 的方式来控制在 displayPriority 增加到 xxx 的时候渲染某些区块了。
当你有渲染耗时的组件,使用 Deferred 做渐进式渲染是不错的注意,它能避免一次 render 由于 JS 执行时间过长导致渲染卡住的现象。
  1. Time slicing
    优化前
fetchItems ({ commit }, { items }) { commit('clearItems') commit('addItems', items) }

优化后
fetchItems ({ commit }, { items, splitCount }) { commit('clearItems') const queue = new JobQueue() splitArray(items, splitCount).forEach( chunk => queue.addJob(done => { // 分时间片提交数据 requestAnimationFrame(() => { commit('addItems', chunk) done() }) }) ) await queue.start() } ?????

  1. Non-reactive data
const data = https://www.it610.com/article/items.map( item => optimizeItem(item) )function optimizeItem (item) { const itemData = https://www.it610.com/article/{ id: uid++, vote: 0 } Object.defineProperty(itemData,'data', { // Mark as non-reactive configurable: false, value: item }) return itemData }

export default { created() { this.scroll = null }, mounted() { this.scroll = new BScroll(this.$el) } }

不需要的数据不用写在data中
  1. Virtual scrolling

原文链接

    推荐阅读