Vue性能優化方法

文中例子來自https://www.youtube.com/watch?v=5B66qer8cZo   部分轉載於鏈接:https://www.jianshu.com/p/f372d0e3de80

函數型組件

由於組件的生命週期處理在框架層面上十分耗時,所以,建議平常儘量使用函數型組件。這樣,可以避免不必要的性能損失。只要在模板上聲明functional屬性,就可以實現函數式組件了:

<template functional>
    <div>
        <div v-if="value" class="on"></div>
        <section v-else class="off"></section>
    </div>
</template>

<script>
    export default {
        props: ['value']
    }
</script>

子組件拆分

另一個優化技巧是,將複雜的耗時計算處理放在子組件中進行處理:

<template>
    <div :style="{opacity: number / 300 }">
        <ChildComp />
    </div>
</template>

<script>
    export default {
        props: ['number'],
        components: {
            ChilComp: {
                methods: {
                    heavy() {
                        // heavy task
                    }
                },
                render(h) {
                    return h('div', this.heavy())
                }
            }
        }
    }
</script>

局部變量

平常在引用computed數據進行計算的時候,可以多使用局部變量,這樣可以避免多次重複計算。

<template>
  <div :style="{ opacity: start / 300 }">{{ result }}</div>
</template>

<script>
export default {
  props: ['start'],
  computed: {
    base () {
      return 42
    },
    result () {
      // 賦值給局部變量,防止重複計算
      const base = this.base;
      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
    },
  },
}
</script>

活用v-show,減少v-if

對於需要頻繁切換的視圖來說,使用v-showv-if更加節約性能。因爲v-show可以避免dom節點的銷燬和重建,所以我們可以將如下的例子

<template functional>
    <div class="cell">
        <div v-if="props.value" class="on">
            <Heavy :n="10000" />
        </div>
        <section v-else class="off">
            <Heavy :n="10000" />
        </section>
    </div>
</template>


改寫爲

<template functional>
    <div class="cell">
        <div v-show="props.value" class="on">
            <Heavy :n="10000" />
        </div>
        <section v-show="!props.value" class="off">
            <Heavy :n="10000" />
        </section>
    </div>
</template>

使用keep-alive

另外一種很常用的優化技巧是使用keep-alive,通常是在路由切換組件中使用:

<template>
    <div id="app">
        <keep-alive>
            <router-view />
        </keep-alive>
    </div>
</template>

延遲加載(defer)

<template>
  <div class="deferred-off">
    <VueIcon icon="fitness_center" class="gigantic"/>

    <h2>I'm an heavy page</h2>

    <Heavy v-for="n in 8" :key="n"/>

    <Heavy class="super-heavy" :n="9999999"/>
  </div>
</template>
<template>
  <div class="deferred-on">
    <VueIcon icon="fitness_center" class="gigantic"/>

    <h2>I'm an heavy page</h2>

    <template v-if="defer(2)">
      <Heavy v-for="n in 8" :key="n"/>
    </template>

    <Heavy v-if="defer(3)" class="super-heavy" :n="9999999"/>
  </div>
</template>

<script>
import Defer from '@/mixins/Defer'
export default {
  mixins: [
    Defer(),
  ],
}
</script>

分批處理(time slicing)

下面這個性能優化的點是前端通用的,可以用requestAnimationFrame分批次執行大數據量的計算,防止一次性執行的數據太大從而阻塞頁面渲染。

比如下面這個例子:

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()
        });
    }));
    
    // 等待所有數據處理完畢
    awiat queue.start();
}

非響應式模式(non-reactive)

對於複雜的數據結構,我們可以顯式聲明爲非響應式,這樣可以避免很多不必要的計算,從而提高性能

const data = items.map(item => optimizeItem(item));

function optimizeItem (item) {
    const itemData = {
        id: uid ++,
        vote: 0
    };
    Object.defineProperty(itemData, 'data', {
        // mark as non-reactive
        configurable: false,
        value: item
    });
    return itemData
}

僅渲染可視化部分

對於無限長列表來說,性能優化主要方法是保持僅渲染可視化部分。

來看一下下面這個例子:

<div class="items no-v">
    <FetchItemViewFunctional v-for="item of items" :key="item.id" :item="item" @vote="voteItem(item)">
    </FetchItemViewFunctional>
</div>

這是最常見的寫法,不過如果列表的內容很多,你就會發現頁面十分的卡頓。此時大家可以利用vue-virtual-scroller這個組件,進行優化:

<recycle-scroller
    class="item"
    :items="items"
    :item-size="24"              
>
    <template v-slot="{item}">
        <FetchItemView :item="item" @vote="voteItem(item)"/>
    </template>
</recycle-scroller>

這樣,可以大大提升組件的流暢度和性能。
 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章