vue性能優(yōu)化

文章目錄

1.代碼優(yōu)化

2.項(xiàng)目優(yōu)化

3.其它優(yōu)化

4.總結(jié)

本文主要針對的是 vue 2.x 版本的性能優(yōu)化,并且從代碼優(yōu)化 和 其他的優(yōu)化去講下在項(xiàng)目開發(fā)時(shí)應(yīng)該注意的優(yōu)化事項(xiàng)。

首先從項(xiàng)目代碼層面方面

1.代碼優(yōu)化

v-if / v-show

這兩個(gè)指令在不同場景的使用下,會(huì)有不同的性能損耗情況撞叨,首先簡單了解下兩者的區(qū)別。

  • v-if 指令在編譯階段就會(huì)編譯成一個(gè)三元運(yùn)算符革屠,通過條件進(jìn)行渲染镊讼。當(dāng)條件的值變化時(shí),會(huì)觸發(fā)對應(yīng)的組件更新揩徊,即會(huì)經(jīng)過 diff 算法腰鬼, 組件初始化、渲染 vnode塑荒、patch等過程熄赡。
  • v-show 指令相比于 v-if 的優(yōu)勢就是它在更新階段僅僅更新了 DOM 的顯隱,少去了很多性能開銷的操作齿税。但是初始化的時(shí)候會(huì)把所有條件節(jié)點(diǎn)都渲染出來
<!-- v-if -->
<template>
    <section>
    <p v-if="props.value">Hello World!</p>
    <p v-else>Vue yyds</p>
  </section>
</template>

<!-- v-show -->
<template>
    <section>
    <p v-show="props.value">Hello World!</p>
    <p v-show="!props.value">Vue yyds</p>
  </section>
</template>
  • 使用場景:

初始化階段: v-if 性能優(yōu)于 v-show
頻繁更新階段: v-show 性能優(yōu)于 v-if

v-for 和 v-if

避免把這兩個(gè)指令放在同一個(gè)節(jié)點(diǎn)

因?yàn)?v-for 指令的優(yōu)先級比 v-if 高彼硫,所以兩個(gè)指令混用的話會(huì)導(dǎo)致每次節(jié)點(diǎn)render的結(jié)果都帶上了條件渲染。當(dāng)數(shù)據(jù)量和節(jié)點(diǎn)復(fù)雜的時(shí)候凌箕,就會(huì)有明顯的性能差拧篮。

當(dāng)我們要循環(huán)節(jié)點(diǎn)和條件判斷的時(shí)候,我們可以先對數(shù)據(jù)進(jìn)行處理后再進(jìn)行 v-for 渲染牵舱,如下例子:

<!-- bad -->
<div v-for="item in list" v-if="item.count > 10" :key="item.id">{{item.name}}</div>

<!-- good -->
<div v-for="item in filters" :key="item.id">{{item.name}}</div>

computed: {
  filters () {
    return this.list.filter(item => item.count > 10)
  }
}

從上面例子不難看出串绩,每個(gè) v-for 節(jié)點(diǎn)處就加了 key 唯一標(biāo)識,這也是提升性能的一個(gè)小點(diǎn)仆葡。使用 key 時(shí)赏参,vue會(huì)基于 key 的變化重新排列元素順序志笼,并且會(huì)移除 key 不存在的元素。

keep-alive

部分場景可以使用 keep-alive 進(jìn)行組件緩存

keep-alive 包裹的組件在經(jīng)過渲染后的 vnode 以及 DOM 都會(huì)被緩存起來把篓,然后下次再次渲染該組件的時(shí)纫溃,直接從緩存中拿到對應(yīng)的 vnode 和 DOM 并且進(jìn)行渲染,并不需要再走一次組件初始化韧掩,render 和 patch 等一系列流程紊浩,減少了 script 的執(zhí)行時(shí)間,性能更好疗锐。

v-slot:slotName / slot="slotName"

vue 2.6 版本坊谁,可以使用 v-slot:slotName 的語法代替 slot="slotName"

  • 舊的寫法在更新時(shí)多了一個(gè)父組件更新的過程,而新的寫法由于直接更新子組件滑臊,就會(huì)更加高效口芍,性能更好,所以推薦始終使用語法 v-slot:slotName
函數(shù)式組件

vue 2.x 的版本雇卷,需要DOM層復(fù)用的情況且場景相對簡單時(shí)鬓椭,可以用 函數(shù)式組件 代替普通組件

函數(shù)式組件生成的是普通的 vnode,不會(huì)存在遞歸子組件的過程关划,所以會(huì)減少一定程度的性能開銷

場景:我在多個(gè)頁面都復(fù)用了一個(gè)頁面渲染的組件小染,不需要一些復(fù)雜的操作,只需要根據(jù)傳參進(jìn)行條件渲染或者循環(huán)渲染等贮折、就可以用如下的例子去進(jìn)行組件的編寫

<!-- 函數(shù)式組件 -->
<template functional>
  <section>
    <div v-if="props.value">Hello World</div>
    <div v-else>Hi~</div>
    <ul>
      <li v-for="item in props.list" :key="item.id">{{item.name}}</li>
    </ul>
  </section>
</template>
子組件拆分

除開代碼維護(hù)的層面裤翩,從性能方面,組件的拆分也是有好處的调榄。

  • 因?yàn)関ue 的更新是組件力度踊赠,如果組件中有數(shù)據(jù)發(fā)生變化,就會(huì)執(zhí)行 render 函數(shù)生成新的 vnode 和舊的 vnode 進(jìn)行 diff振峻。哪怕這個(gè)數(shù)據(jù)只影響到一個(gè)元素渲染臼疫,其他元素也需要在 diff 過程中進(jìn)行比較。極端情況是假設(shè)這個(gè)大組件里面有個(gè)倒計(jì)時(shí)扣孟。
  • 如果組件拆分得當(dāng)?shù)脑捥痰蹋蟛糠值臄?shù)據(jù)改動(dòng)只會(huì)影響到子組件本身進(jìn)行 diff ==> 渲染。所以合理得對這種大組件進(jìn)行拆分凤价,應(yīng)用的更新效率會(huì)更高鸽斟。

例如:

<!-- 拆分前 -->
<template>
  <div :style="{ opacity: number / 300 }">
    <div>{{ heavy() }}</div>
  </div>
</template>

<script>
export default {
  props: ['number'],
  methods: {
    heavy () {
      const n = 100000
      let result = 0
      for (let i = 0; i < n; i++) {
        result += Math.sqrt(Math.cos(Math.sin(42)))
      }
      return result
    },
  },
}
</script>


<!-- 拆分后 -->
<template>
  <div :style="{ opacity: number / 300 }">
    <ChildComp/>
  </div>
</template>

<script>
export default {
  components: {
    ChildComp: {
      methods: {
        heavy () {
          const n = 100000
          let result = 0
          for (let i = 0; i < n; i++) {
            result += Math.sqrt(Math.cos(Math.sin(42)))
          }
          return result
        },
      },
      render (h) {
        return h('div', this.heavy())
      },
    },
  },
  props: ['number'],
}
</script>
響應(yīng)式數(shù)據(jù)優(yōu)化
data的優(yōu)化

vue 在組件實(shí)例初始化的時(shí)候會(huì)對data進(jìn)行響應(yīng)式處理,能夠減少一個(gè)數(shù)據(jù)就是減少一點(diǎn)點(diǎn)的性能開銷利诺。而且一些常量數(shù)據(jù)不應(yīng)該在data里面進(jìn)行定義富蓄,簡單總結(jié)為以下三點(diǎn):

  • 減少無用的data數(shù)據(jù)

  • 減少數(shù)據(jù)被observer

  • 數(shù)據(jù)盡量扁平化

局部變量緩存響應(yīng)式數(shù)據(jù)

先直接看對比代碼

// 優(yōu)化前
// ··········
computed: {
  base () {
    return 42
  },
    result () {
      let result = this.start
      for (let i = 0; i < 1000; i++) {
        result += Math.sqrt(Math.cos(Math.sin(this.base))) + this.base * this.base + this.base + this.base * 2 + this.base * 3
      }
      return result
    },
}

// 優(yōu)化后
// ·········
computed: {
  base () {
    return 42
  },
    result ({ base, start }) {
      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
    },
}

優(yōu)化前每次調(diào)用 this.base 的時(shí)候,由于它是個(gè)響應(yīng)式數(shù)據(jù)慢逾,每次都會(huì)調(diào)用都會(huì)觸發(fā)它的 getter立倍,進(jìn)而執(zhí)行依賴收集等邏輯灭红。

優(yōu)化后先把 this.base 緩存到局部變量,后面重復(fù)調(diào)用的時(shí)候就不會(huì)頻繁的觸發(fā)到 getter 的邏輯處理

computed

計(jì)算屬性是基于它們的響應(yīng)式依賴進(jìn)行緩存的口注。只在相關(guān)響應(yīng)式依賴發(fā)生改變時(shí)它們才會(huì)重新求值变擒。這就意味著只要 數(shù)據(jù) 還沒有發(fā)生改變,多次訪問 計(jì)算屬性會(huì)立即返回之前的計(jì)算結(jié)果寝志,可以極大提升性能娇斑。

例如:

<template>
  <div>{{count}}</div>
</template>
<script>
  export default {
    computed: {
      count () {
      let result
      // 復(fù)雜的計(jì)算操作
      return result
      }
    }
  }
</script>

2.項(xiàng)目優(yōu)化

路由懶加載

在vue-router的配置文件里,定義一個(gè)能夠被 Webpack 自動(dòng)代碼分割的異步組件

const Hello = () => import('//hello.vue')
const router = new VueRouter({
  routes: [
    { path: '/hello', component: Hello },
    { path: '/world', component: import('//world.vue') }
  ]
})
組件按需加載

element-ui 為例子材部,有些項(xiàng)目用ui組件庫的時(shí)候使用的并不多毫缆,可以按需加載適當(dāng)優(yōu)化項(xiàng)目的體積

import {Button} from 'element-ui'

Vue.use(Button)

3.其它優(yōu)化

1.圖片懶加載
2.節(jié)流 / 防抖
3.長列表的虛擬滾動(dòng)

4.總結(jié)

1.減少?zèng)]必要的渲染機(jī)制
2.減少全量加載,適當(dāng)?shù)膽屑虞d
3.正確的使用vue的每個(gè)api乐导,本身vue這個(gè)框架就對性能方面做了很多處理苦丁,正常使用就不會(huì)出現(xiàn)性能瓶頸

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市物臂,隨后出現(xiàn)的幾起案子芬骄,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件濒析,死亡現(xiàn)場離奇詭異魔策,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胧沫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人规丽,你說我怎么就攤上這事∑埠兀” “怎么了赌莺?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長松嘶。 經(jīng)常有香客問我艘狭,道長,這世上最難降的妖魔是什么翠订? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任巢音,我火速辦了婚禮,結(jié)果婚禮上尽超,老公的妹妹穿的比我還像新娘官撼。我一直安慰自己,他們只是感情好似谁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布傲绣。 她就那樣靜靜地躺著掠哥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪秃诵。 梳的紋絲不亂的頭發(fā)上续搀,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機(jī)與錄音顷链,去河邊找鬼目代。 笑死,一個(gè)胖子當(dāng)著我的面吹牛嗤练,可吹牛的內(nèi)容都是我干的榛了。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼煞抬,長吁一口氣:“原來是場噩夢啊……” “哼霜大!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起革答,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤战坤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后残拐,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體途茫,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年溪食,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了囊卜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡错沃,死狀恐怖栅组,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情枢析,我是刑警寧澤玉掸,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站醒叁,受9級特大地震影響司浪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜辐益,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一断傲、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧智政,春花似錦认罩、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宦搬。三九已至,卻和暖如春劫拗,著一層夾襖步出監(jiān)牢的瞬間间校,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工页慷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留憔足,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓酒繁,卻偏偏與公主長得像滓彰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子州袒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容