vue編碼之優(yōu)化手段

性能優(yōu)化本身就是一個很大的話題,并且它沒有一個定式,最好是在具體的項目中具體分析,而不是說看到一個優(yōu)化技巧一定要用在項目當(dāng)中,這篇文章主要聊聊在vue編碼階段有哪些常見的優(yōu)化手段。
?? 使用 key
關(guān)于key在這篇 請闡述vue的diff算法文章有說到,key值在對比新舊虛擬節(jié)點時可以辨識虛擬節(jié)點,在更新子節(jié)點的時候,需要將舊虛擬節(jié)點列表與新虛擬節(jié)點相同的節(jié)點進行更新。如果在對比過程中設(shè)置了key值,那么對比的速度就會快很多。對于通過循環(huán)生成的列表,應(yīng)該給每個列表項添加一個穩(wěn)定且唯一的key,這樣有利于在列表發(fā)生變化時,盡量少刪除、新增、改動元素。
?? 使用凍結(jié)對象
什么是凍結(jié)對象?凍結(jié)對象其實就是通過Object.freeze(傳一個對象)將對象凍結(jié),凍結(jié)之后,這個對象的屬性就不能修改添加了,是不可變的,當(dāng)然數(shù)組也能凍結(jié),凍結(jié)后什么操作都不行,增刪改就不要想了,由于凍結(jié)對象后不可變,vue會對凍結(jié)對象進行優(yōu)化處理,vue不會將凍結(jié)的對象處理成響應(yīng)式。我們在實際項目開發(fā)中可能會處理不會改變的數(shù)據(jù),它只需要渲染到頁面上就行了,所以這些數(shù)據(jù)是沒必要變成響應(yīng)式的,這時使用凍結(jié)對象可以減少vue將對象變成響應(yīng)式過程這個時間。
當(dāng)然它也有一個弊端,就是將來想修改對象中的數(shù)據(jù),由于不是響應(yīng)式的,所以也不會渲染在頁面上。
? 使用計算屬性
如果模板中某個數(shù)據(jù)會使用多次,并且該數(shù)據(jù)是通過計算得到的,盡量使用計算屬性,我們都知道計算屬性是有緩存的,計算屬性函數(shù)依賴的數(shù)據(jù)在沒有發(fā)生變化的情況下,會反復(fù)讀取緩存數(shù)據(jù),而計算屬性函數(shù)并不會反復(fù)執(zhí)行,但也有缺陷,就是不能傳參數(shù)。
?? 非實時綁定的表單項
當(dāng)使用v-model綁定一個表單項時,當(dāng)用戶改變表單項的狀態(tài)時,也會隨之改變數(shù)據(jù),從而導(dǎo)致vue發(fā)生重新渲染(rerender),這會帶來一些性能的開銷。
特別是當(dāng)用戶改變表單項時,頁面有一些動畫正在進行中,由于JS執(zhí)行線程和瀏覽器渲染線程是互斥的,最終會導(dǎo)致動畫出現(xiàn)卡頓。
我們可以通過使用lazy或不使用v-model的方式解決問題,但要注意,這樣可能導(dǎo)致在某個時間段內(nèi)數(shù)據(jù)和表單項的值不一致。
一個簡單例子: 插入一個任務(wù)到列表中

當(dāng)我們直接使用v-model進行雙向綁定,先不加lazy修飾符,然后將transition過渡時間調(diào)整為5s
<template>
<div id="app">
<input
type="text"
placeholder="今天的任務(wù)完成了嗎?"
v-model="message"
@change="addContent"
/>
<button @click="shuffle">隨機排序</button>
<transition-group name="nums" tag="ul" class="box">
<li v-for="(item, i) in likeList" :key="item" class="task">
<span>{{ item }}</span>
<button @click="deleteContent(i)">完成</button>
</li>
</transition-group>
</div>
</template>
<script>
export default {
data() {
return {
likeList: ["寫代碼", "看書", "吃飯", "追女孩子"],
message: "",
};
},
methods: {
deleteContent(i) {
this.likeList.splice(i, 1);
},
shuffle() {
this.likeList.sort(() => Math.random() - 0.5);
},
addContent() {
if (this.likeList.includes(this.message.replace(/\s+/g, ""))) {
alert("當(dāng)前任務(wù)已存在,請重新輸入!");
this.message = "";
return;
}
this.likeList.unshift(this.message.replace(/\s+/g, ""));
this.message = "";
},
},
};
</script>
<style>
#app {
width: 500px;
margin: 0 auto;
}
* {
list-style: none;
}
input {
width: 600px;
height: 40px;
font-size: 24px;
border: none;
outline: none;
border-style: solid;
border-color: #ddd;
background: paleturquoise;
margin-bottom: 15px;
text-indent: 1em;
}
.box {
width: 500px;
padding: 0 20px;
margin-bottom: 200px;
}
.task {
width: 100%;
height: 50px;
line-height: 50px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #ddd;
}
.task button {
width: 70px;
height: 30px;
}
.nums-enter {
opacity: 0;
transform: translateX(-300px);
}
.nums-enter-active,
.nums-leave-active,
.nums-move {
/* 修改這里的時間即可 */
transition: 5s;
}
.nums-leave-to {
opacity: 0;
transform: translateX(300px);
}
.nums-leave-active {
position: absolute;
}
</style>
效果如下:
我們可以很明顯看到當(dāng)添加一項內(nèi)容的時候,不停的輸入內(nèi)容會導(dǎo)致頁面渲染變慢

然后給v-model加上lazy修飾符再看看,是不是跟不加有很大區(qū)別??

?? 使用v-show替代v-if
對于頻繁切換顯示狀態(tài)的元素,使用v-show可以保證虛擬dom樹的穩(wěn)定,避免頻繁的新增和刪除元素,尤其是當(dāng)內(nèi)部包含大量的dom元素的節(jié)點。
?? 使用延遲裝載(defer)
使用延遲裝載主要解決白屏問題,首頁白屏?xí)r間主要受兩個因素的影響:
打包體積過大
包的體積過大需要消耗大量的傳輸時間,導(dǎo)致Js傳輸完成前頁面只有一個
<div>,沒有可以顯示的內(nèi)容。需要立即渲染的內(nèi)容過多
JS傳輸完成后,瀏覽器開始執(zhí)行JS構(gòu)造頁面。但是可能一開始要渲染的組件太多了,不僅會導(dǎo)致Js執(zhí)行時間很長,而且執(zhí)行完后瀏覽器要渲染的元素過多,從而導(dǎo)致白屏
打包體積過大需要自行優(yōu)化打包體積,這里就不說了,主要聊聊渲染內(nèi)容過多的問題。
一個可行的辦法就是延遲裝載組件,讓組件按照指定的先后順序依次一個一個渲染出來。
延遲裝載是一個思路,本質(zhì)上就是利用requestAnimationFrame 事件分批渲染內(nèi)容,它的具體實現(xiàn)多種多樣。
?? keep-alive組件
關(guān)于keep-alive 可以看看這篇文章:請闡述keep-alive組件的作用和原理
?? 使用長列表優(yōu)化
關(guān)于長列表優(yōu)化 可以看看這篇文章:vue編碼之長列表優(yōu)化
?? 好了, 以上就是我的分享,歡迎大家在評論區(qū)討論鴨~
希望小伙伴們點贊 ?? 支持一下哦~ ??,我會更有動力的 ??
