函数型组件 未优化
1 2 3 4 5 6 7 8 9 10 11 12 <template > <div class ="cell" > <div v-if ="value" class ="on" > </div > <section v-else class ="off" > </section > </div > </template > <script > export default { props: ['value' ] } </script >
优化后
1 2 3 4 5 6 7 8 9 10 11 12 <template functional > <div class ="cell" > <div v-if ="props.value" class ="on" > </div > <section v-else class ="off" > </section > </div > </template > <script > export default { props: ['value' ] } </script >
子组件拆分 未优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <template > <div :style ="{ opacity: number / 300 }" > <div > {{ heavy () }} </div > </div > </template > <script > export default { props: ['number'], methods: { heavy () { /* HEAVY TASK */ } } } </script >
已优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <template > <div :style ="{ opacity: number / 300 }" > <ChildComp /> </div > </template > <script > export default { props: ['number' ], components: { ChildComp: { methods: { heavy () { } }, render (h) { return h('div' , this .heavy()) } } } } </script >
尽量将复杂逻辑拆分到子组件中
局部变量 未优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <template > <div :style ="{ opacity: start / 300 }" > {{ result }} </div > </template > <script > import { heavy } from '@/utils' export default { props: ['start'], computed: { base () { return 42 }, result () { let result = this.start for (let i = 0; i < 1000 ; i ++) { result += heavy(this.base) } return result } } } </script >
已优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <template > <div :style ="{ opacity: start / 300 }" > {{ result }} </div > </template > <script > import { heavy } from '@/utils' export default { props: ['start'], computed: { base () { return 42 }, result () { const base = this.base let result = this.start for (let i = 0; i < 1000 ; i ++) { result += heavy(base) } return result } } } </script >
使用局部变量缓存计算属性,不用每次去读取,提高性能
活用v-show,少用v-if 未优化
1 2 3 4 5 6 7 8 9 10 <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 >
已优化
1 2 3 4 5 6 7 8 9 10 <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 未优化
1 2 3 4 5 <template > <div id ="app" > <router-view /> </div > </template >
已优化
1 2 3 4 5 6 7 <template > <div id ="app" > <keep-alive > <router-view /> </keep-alive > </div > </template >
缓存组件
活用延迟装载(defer) 未优化
1 2 3 4 5 6 7 <template > <div > <h2 > I'm an heavy page</h2 > <Heavy v-for ="n in 10" :key ="n" /> <Heavy class ="super-heavy" :n ="9999999" /> </div > </template >
已优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 <template> <div> <h2>I'm an heavy page</h2> <template v-if="defer(2)"> <Heavy v-for="n in 10" :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> Defer mixin export default function (count = 10) { return { data () { return { displayPriority: 0 } }, mounted () { this.runDisplayPriority() }, methods: { runDisplayPriority () { const step = () => { requestAnimationFrame(() => { this.displayPriority++ if (this.displayPriority < count) { step() } }) } step() }, defer (priority) { return this.displayPriority >= priority } } } }
无法实际优化性能,只是改变装载顺序,让用户感觉流畅
分批处理 未优化
1 2 3 4 fetchItems ({ commit }, { items }) { commit ('clearItems' ) commit ('addItems' , items) }
已优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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 2 3 4 5 6 7 const data = items.map( item => ({ id : uid++, data : item, vote : 0 }) )
已优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const data = items.map( item => optimizeItem(item) ) function optimizeItem (item ) { const itemData = { id: uid++, vote: 0 } Object .defineProperty(itemData, 'data' , { configurable: false , value: item }) return itemData }
优先渲染用户可见的 未优化
1 2 3 4 5 6 7 8 <div class ="items no-v" > <FetchItemViewFunctional v-for ="item of items" :key="item.id" :item ="item" @vote="voteItem(item)" /> </div >
已优化
1 2 3 4 5 6 7 8 9 10 11 12 <recycle-scroller class="items" :items="items" :item-size="24" > <template v-slot =" { item } " > <FetchItemView :item="item" @vote="voteItem(item)" /> </template > </recycle-scroller >