The examples are from https://www.youtube.com/watch?v=5B66qer8cZo Partially reproduced in link: https://www.jianshu.com/p/f372d0e3de80
Functional components
Because the life cycle processing of components is very time-consuming at the framework level, it is recommended to use functional components as much as possible. In this way, unnecessary performance loss can be avoided. As long as the functional attribute is declared on the template, the functional component can be implemented:
<template functional> <div> <div v-if="value" class="on"></div> <section v-else class="off"></section> </div> </template> <script> export default { props: ['value'] } </script>
Sub component split
Another optimization technique is to put complex and time-consuming computing processing into subcomponents:
<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>
local variable
Usually, when using calculated data for calculation, you can use more local variables, which can avoid repeated calculation.
<template> <div :style="{ opacity: start / 300 }">{{ result }}</div> </template> <script> export default { props: ['start'], computed: { base () { return 42 }, result () { // Assign to local variable to prevent repeated calculation 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>
Using v-show to reduce v-if
For views that need to switch frequently, using v-show is more economical than v-if. Because v-show can avoid the destruction and reconstruction of dom nodes, we can use the following example
<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> //Rewrite as <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>
Use keep alive
Another common optimization technique is to use keep alive, which is usually used in the routing switching component:
<template> <div id="app"> <keep-alive> <router-view /> </keep-alive> </div> </template>
Defer load
<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
The following performance optimization points are common to the front-end. You can use the requestAnimationFrame to perform large amount of data calculation in batches to prevent one-time execution of too large data to block page rendering.
For example:
fetchItems({ commit }, { items }) { commit('clearItems'); commit('addItems', items) } //It can be rewritten as: fetchItems({ commit }, { items, splitCount }) { commit('clearItems'); //Create a new queue const queue = new JobQueue(); splitArray(items, splitCount).forEach(chunk => queue.addJob(done => { // Fragmentation requestAnimationFrame(() => { commit('addItems', chunk); done() }); })); // Wait for all data processing to complete awiat queue.start(); }
Non reactive mode
For complex data structures, we can explicitly declare them as nonresponsive, which can avoid many unnecessary calculations and improve performance
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 }
Rendering visualization only
For an infinite list, the main method of performance optimization is to keep rendering only the visual part.
Here's an example:
<div class="items no-v"> <FetchItemViewFunctional v-for="item of items" :key="item.id" :item="item" @vote="voteItem(item)"> </FetchItemViewFunctional> </div>
This is the most common way to write, but if there is a lot of content in the list, you will find that the page is very stuck. At this time, you can use vue-virtual-scroller This component is optimized:
<recycle-scroller class="item" :items="items" :item-size="24" > <template v-slot="{item}"> <FetchItemView :item="item" @vote="voteItem(item)"/> </template> </recycle-scroller>
In this way, the fluency and performance of components can be greatly improved.