揭秘 Vue.js 九個性能優化技巧

2021-03-02 前端從進階到入院

點上方藍字關注公眾號「前端從進階到入院」

精選原創好文、進階交流群助你進入大廠

這篇文章主要參考了 Vue.js 核心成員 Guillaume Chau 在 19 年美國的 Vue conf 分享的主題:9 Performance secrets revealed,分享中提到了九個 Vue.js 性能優化的技巧。

我看完他的分享 PPT後,也閱讀了相關的項目源碼,在深入了解它的優化原理後,把其中一些優化技巧也應用到了我平時的工作中,取得了相當不錯的效果。

這個分享可謂是非常實用了,但是知道和關注的人似乎並不多,到目前為止,該項目也只有可憐的幾百個 star。雖然距大佬的分享已經有兩年時間,但是其中的優化技巧並沒有過時,為了讓更多的人了解並學習到其中的實用技巧,我決定對他的分享做二次加工,詳細闡述其中的優化原理,並做一定程度的擴展和延伸。

本文主要還是針對 Vue.js 2.x 版本,畢竟接下來一段時間,Vue.js 2.x 還是我們工作中的主流版本。

我建議你在學習這篇文章的時候可以拉取項目的源碼,並且本地運行,查看優化前後的效果差異。

Functional components

第一個技巧,函數式組件,你可以查看這個在線示例

優化前的組件代碼如下:

<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>

優化後的組件代碼如下:

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

然後我們在父組件各渲染優化前後的組件 800 個,並在每一幀內部通過修改數據來觸發組件的更新,開啟 Chrome 的 Performance 面板記錄它們的性能,得到如下結果。

優化前:

優化後:

對比這兩張圖我們可以看到優化前執行 script 的時間要多於優化後的,而我們知道 JS 引擎是單線程的運行機制,JS 線程會阻塞 UI 線程,所以當腳本執行時間過長,就會阻塞渲染,導致頁面卡頓。而優化後的 script 執行時間短,所以它的性能更好。

那麼,為什麼用函數式組件 JS 的執行時間就變短了呢?這要從函數式組件的實現原理說起了,你可以把它理解成一個函數,它可以根據你傳遞的上下文數據渲染生成一片 DOM。

函數式組件和普通的對象類型的組件不同,它不會被看作成一個真正的組件,我們知道在 patch 過程中,如果遇到一個節點是組件 vnode,會遞歸執行子組件的初始化過程;而函數式組件的 render 生成的是普通的 vnode,不會有遞歸子組件的過程,因此渲染開銷會低很多。

因此,函數式組件也不會有狀態,不會有響應式數據,生命周期鉤子函數這些東西。你可以把它當成把普通組件模板中的一部分 DOM 剝離出來,通過函數的方式渲染出來,是一種在 DOM 層面的復用。

Child component splitting

第二個技巧,子組件拆分,你可以查看這個在線示例。

優化前的組件代碼如下:

<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>

然後我們在父組件各渲染優化前後的組件 300 個,並在每一幀內部通過修改數據來觸發組件的更新,開啟 Chrome 的 Performance 面板記錄它們的性能,得到如下結果。

優化前:

優化後:

對比這兩張圖我們可以看到優化後執行 script 的時間要明顯少於優化前的,因此性能體驗更好。

那麼為什麼會有差異呢,我們來看優化前的組件,示例通過一個 heavy 函數模擬了一個耗時的任務,且這個函數在每次渲染的時候都會執行一次,所以每次組件的渲染都會消耗較長的時間執行 JavaScript。

而優化後的方式是把這個耗時任務 heavy 函數的執行邏輯用子組件 ChildComp 封裝了,由於 Vue 的更新是組件粒度的,雖然每一幀都通過數據修改導致了父組件的重新渲染,但是 ChildComp 卻不會重新渲染,因為它的內部也沒有任何響應式數據的變化。所以優化後的組件不會在每次渲染都執行耗時任務,自然執行的 JavaScript 時間就變少了。

不過針對這個優化的方式我提出了一些不同的看法,詳情可以點開這個 issue,我認為這個場景下的優化用計算屬性要比子組件拆分要好。得益於計算屬性自身緩存特性,耗時的邏輯也只會在第一次渲染的時候執行,而且使用計算屬性也沒有額外渲染子組件的開銷。

在實際工作中,使用計算屬性是優化性能的場景會有很多,畢竟它也體現了一種空間換時間的優化思想。

Local variables

第三個技巧,局部變量,你可以查看這個在線示例。

優化前的組件代碼如下:

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

<script>
export default {
  props: ['start'],
  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
    },
  },
}
</script>

優化後的組件代碼如下:

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

<script>
export default {
  props: ['start'],
  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
    },
  },
}
</script>

然後我們在父組件各渲染優化前後的組件 300 個,並在每一幀內部通過修改數據來觸發組件的更新,開啟 Chrome 的 Performance 面板記錄它們的性能,得到如下結果。

優化前:

優化後:

對比這兩張圖我們可以看到優化後執行 script 的時間要明顯少於優化前的,因此性能體驗更好。

這裡主要是優化前後組件的計算屬性 result 的實現差異,優化前的組件多次在計算過程中訪問 this.base,而優化後的組件會在計算前先用局部變量 base 緩存 this.base,後面則直接訪問 base變量。

那麼為啥這個差異會造成性能上的差異呢,原因是你每次訪問 this.base 的時候,由於 this.base 是一個響應式對象,所以會觸發它的 getter,進而會執行依賴收集相關邏輯代碼。類似的邏輯執行多了,像示例這樣,幾百次循環更新幾百個組件,每個組件觸發 computed 重新計算,然後又多次執行依賴收集相關邏輯,性能自然就下降了。

從需求上來說,this.base 執行一次依賴收集就夠了,因此我們只需要把它的 getter 求值結果返回給局部變量 base,後續再次訪問 base 的時候就不會觸發 getter,也不會走依賴收集的邏輯了,性能自然就得到了提升。

這是一個非常實用的性能優化技巧。因為很多人在開發 Vue.js 項目的時候,每當取變量的時候就習慣性直接寫 this.xxx 了,因為大部分人並不會注意到訪問 this.xxx 背後做的事情。在訪問次數不多的時候,性能問題並沒有凸顯,但是一旦訪問次數變多,比如在一個大循環中多次訪問,類似示例這種場景,就會產生性能問題了。

我之前給 ZoomUI 的 Table 組件做性能優化的時候,在 render table body 的時候就使用了局部變量的優化技巧,並寫了 benchmark 做性能對比:渲染 1000 * 10 的表格,ZoomUI Table 的更新數據重新渲染的性能要比 ElementUI 的 Table 性能提升了近一倍。

Reuse DOM with v-show

第四個技巧,使用 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>

然後我們在父組件各渲染優化前後的組件 200 個,並在每一幀內部通過修改數據來觸發組件的更新,開啟 Chrome 的 Performance 面板記錄它們的性能,得到如下結果。

優化前:

優化後:

對比這兩張圖我們可以看到優化後執行 script 的時間要明顯少於優化前的,因此性能體驗更好。

優化前後的主要區別是用 v-show 指令替代了 v-if 指令來替代組件的顯隱,雖然從表現上看,v-show 和 v-if 類似,都是控制組件的顯隱,但內部實現差距還是很大的。

v-if 指令在編譯階段就會編譯成一個三元運算符,條件渲染,比如優化前的組件模板經過編譯後生成如下渲染函數:

function render() {
  with(this) {
    return _c('div', {
      staticClass: "cell"
    }, [(props.value) ? _c('div', {
      staticClass: "on"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1) : _c('section', {
      staticClass: "off"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1)])
  }
}

當條件 props.value 的值變化的時候,會觸發對應的組件更新,對於 v-if 渲染的節點,由於新舊節點 vnode 不一致,在核心 diff 算法比對過程中,會移除舊的 vnode 節點,創建新的 vnode 節點,那麼就會創建新的 Heavy 組件,又會經歷 Heavy 組件自身初始化、渲染 vnode、patch 等過程。

因此使用 v-if 每次更新組件都會創建新的 Heavy 子組件,當更新的組件多了,自然就會造成性能壓力。

而當我們使用 v-show 指令,優化後的組件模板經過編譯後生成如下渲染函數:

function render() {
  with(this) {
    return _c('div', {
      staticClass: "cell"
    }, [_c('div', {
      directives: [{
        name: "show",
        rawName: "v-show",
        value: (props.value),
        expression: "props.value"
      }],
      staticClass: "on"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1), _c('section', {
      directives: [{
        name: "show",
        rawName: "v-show",
        value: (!props.value),
        expression: "!props.value"
      }],
      staticClass: "off"
    }, [_c('Heavy', {
      attrs: {
        "n": 10000
      }
    })], 1)])
  }
}

當條件 props.value 的值變化的時候,會觸發對應的組件更新,對於 v-show 渲染的節點,由於新舊 vnode 一致,它們只需要一直 patchVnode 即可,那麼它又是怎麼讓 DOM 節點顯示和隱藏的呢?

原來在 patchVnode 過程中,內部會對執行 v-show 指令對應的鉤子函數 update,然後它會根據 v-show 指令綁定的值來設置它作用的 DOM 元素的 style.display 的值控制顯隱。

因此相比於 v-if 不斷刪除和創建函數新的 DOM,v-show 僅僅是在更新現有 DOM 的顯隱值,所以 v-show 的開銷要比 v-if 小的多,當其內部 DOM 結構越複雜,性能的差異就會越大。

但是 v-show 相比於 v-if 的性能優勢是在組件的更新階段,如果僅僅是在初始化階段,v-if 性能還要高於 v-show,原因是在於它僅僅會渲染一個分支,而 v-show 把兩個分支都渲染了,通過 style.display 來控制對應 DOM 的顯隱。

在使用 v-show 的時候,所有分支內部的組件都會渲染,對應的生命周期鉤子函數都會執行,而使用 v-if 的時候,沒有命中的分支內部的組件是不會渲染的,對應的生命周期鉤子函數都不會執行。

因此你要搞清楚它們的原理以及差異,才能在不同的場景使用適合的指令。

KeepAlive

第五個技巧,使用 KeepAlive 組件緩存 DOM,你可以查看這個在線示例。

優化前的組件代碼如下:

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

優化後的組件代碼如下:

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

我們點擊按鈕在 Simple page 和 Heavy Page 之間切換,會渲染不同的視圖,其中 Heavy Page 的渲染非常耗時。我們開啟 Chrome 的 Performance 面板記錄它們的性能,然後分別在優化前後執行如上的操作,會得到如下結果。

優化前:

優化後:

對比這兩張圖我們可以看到優化後執行 script 的時間要明顯少於優化前的,因此性能體驗更好。

在非優化場景下,我們每次點擊按鈕切換路由視圖,都會重新渲染一次組件,渲染組件就會經過組件初始化,render、patch 等過程,如果組件比較複雜,或者嵌套較深,那麼整個渲染耗時就會很長。

而在使用 KeepAlive 後,被 KeepAlive 包裹的組件在經過第一次渲染後,的 vnode 以及 DOM 都會被緩存起來,然後再下一次再次渲染該組件的時候,直接從緩存中拿到對應的 vnode 和 DOM,然後渲染,並不需要再走一次組件初始化,render 和 patch 等一系列流程,減少了 script 的執行時間,性能更好。

但是使用 KeepAlive 組件並非沒有成本,因為它會佔用更多的內存去做緩存,這是一種典型的空間換時間優化思想的應用。

Deferred features

第六個技巧,使用 Deferred 組件延時分批渲染組件,你可以查看這個在線示例。

優化前的組件代碼如下:

<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>

我們點擊按鈕在 Simple page 和 Heavy Page 之間切換,會渲染不同的視圖,其中 Heavy Page 的渲染非常耗時。我們開啟 Chrome 的 Performance 面板記錄它們的性能,然後分別在優化前後執行如上的操作,會得到如下結果。

優化前:

優化後:

對比這兩張圖我們可以發現,優化前當我們從 Simple Page 切到 Heavy Page 的時候,在一次 Render 接近結尾的時候,頁面渲染的仍然是 Simple Page,會給人一種頁面卡頓的感覺。而優化後當我們從 Simple Page 切到 Heavy Page 的時候,在一次 Render 靠前的位置頁面就已經渲染了 Heavy Page 了,並且 Heavy Page 是漸進式渲染出來的。

優化前後的差距主要是後者使用了 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
      }
    }
  }
}

Defer 的主要思想就是把一個組件的一次渲染拆成多次,它內部維護了 displayPriority 變量,然後在通過 requestAnimationFrame 在每一幀渲染的時候自增,最多加到 count。然後使用 Defer mixin 的組件內部就可以通過 v-if="defer(xxx)" 的方式來控制在 displayPriority 增加到 xxx 的時候渲染某些區塊了。

當你有渲染耗時的組件,使用 Deferred 做漸進式渲染是不錯的注意,它能避免一次 render 由於 JS 執行時間過長導致渲染卡住的現象。

Time slicing

第七個技巧,使用 Time slicing 時間片切割技術,你可以查看這個在線示例。

優化前的代碼如下:

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()
      })
    })
  )
  await queue.start()
}

我們先通過點擊 Genterate items 按鈕創建 10000 條假數據,然後分別在開啟和關閉 Time-slicing 的情況下點擊 Commit items 按鈕提交數據,開啟 Chrome 的 Performance 面板記錄它們的性能,會得到如下結果。

優化前:

優化後:

對比這兩張圖我們可以發現,優化前總的 script 執行時間要比優化後的還要少一些,但是從實際的觀感上看,優化前點擊提交按鈕,頁面會卡死 1.2 秒左右,在優化後,頁面不會完全卡死,但仍然會有渲染卡頓的感覺。

那麼為什麼在優化前頁面會卡死呢?因為一次性提交的數據過多,內部 JS 執行時間過長,阻塞了 UI 線程,導致頁面卡死。

優化後,頁面仍有卡頓,是因為我們拆分數據的粒度是 1000 條,這種情況下,重新渲染組件仍然有壓力,我們觀察 fps 只有十幾,會有卡頓感。通常只要讓頁面的 fps 達到 60,頁面就會非常流暢,如果我們把數據拆分粒度變成 100 條,基本上 fps 能達到 50 以上,雖然頁面渲染變流暢了,但是完成 10000 條數據總的提交時間還是變長了。

使用 Time slicing技術可以避免頁面卡死,通常我們在這種耗時任務處理的時候會加一個 loading 效果,在這個示例中,我們可以開啟 loading animation,然後提交數據。對比發現,優化前由於一次性提交數據過多,JS 一直長時間運行,阻塞 UI 線程,這個 loading 動畫是不會展示的,而優化後,由於我們拆成多個時間片去提交數據,單次 JS 運行時間變短了,這樣 loading 動畫就有機會展示了。

這裡要注意的一點,雖然我們拆時間片使用了 requestAnimationFrame API,但是使用 requestAnimationFrame 本身是不能保證滿幀運行的,requestAnimationFrame 保證的是在瀏覽器每一次重繪後會執行對應傳入的回調函數,想要保證滿幀,只能讓 JS 在一個 Tick 內的運行時間不超過 17ms。

Non-reactive data

第八個技巧,使用 Non-reactive data ,你可以查看這個在線示例。

優化前代碼如下:

const data = items.map(
  item => ({
    id: uid++,
    data: item,
    vote: 0
  })
)

優化後代碼如下:

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
}

還是前面的示例,我們先通過點擊 Genterate items 按鈕創建 10000 條假數據,然後分別在開啟和關閉 Partial reactivity 的情況下點擊 Commit items 按鈕提交數據,開啟 Chrome 的 Performance 面板記錄它們的性能,會得到如下結果。

優化前:

優化後:

對比這兩張圖我們可以看到優化後執行 script 的時間要明顯少於優化前的,因此性能體驗更好。

之所以有這種差異,是因為內部提交的數據的時候,會默認把新提交的數據也定義成響應式,如果數據的子屬性是對象形式,還會遞歸讓子屬性也變成響應式,因此當提交數據很多的時候,這個過程就變成了一個耗時過程。

而優化後我們把新提交的數據中的對象屬性 data 手動變成了 configurable 為 false,這樣內部在 walk 時通過 Object.keys(obj) 獲取對象屬性數組會忽略 data,也就不會為 data 這個屬性 defineReactive,由於 data 指向的是一個對象,這樣也就會減少遞歸響應式的邏輯,相當於減少了這部分的性能損耗。數據量越大,這種優化的效果就會更明顯。

其實類似這種優化的方式還有很多,比如我們在組件中定義的一些數據,也不一定都要在 data 中定義。有些數據我們並不是用在模板中,也不需要監聽它的變化,只是想在組件的上下文中共享這個數據,這個時候我們可以僅僅把這個數據掛載到組件實例 this 上,例如:

export default {
  created() {
    this.scroll = null
  },
  mounted() {
    this.scroll = new BScroll(this.$el)
  }
}

這樣我們就可以在組件上下文中共享 scroll 對象了,即使它不是一個響應式對象。

Virtual scrolling

第九個技巧,使用 Virtual scrolling ,你可以查看這個在線示例。

優化前組件的代碼如下:

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

優化後代碼如下:

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

還是前面的示例,我們需要開啟 View list,然後點擊 Genterate items 按鈕創建 10000 條假數據(注意,線上示例最多只能創建 1000 條數據,實際上 1000 條數據並不能很好地體現優化的效果,所以我修改了源碼的限制,本地運行,創建了 10000 條數據),然後分別在 Unoptimized 和 RecycleScroller 的情況下點擊 Commit items 按鈕提交數據,滾動頁面,開啟 Chrome 的 Performance 面板記錄它們的性能,會得到如下結果。

優化前:

優化後:

對比這兩張圖我們發現,在非優化的情況下,10000 條數據在滾動情況下 fps 只有個位數,在非滾動情況下也就十幾,原因是非優化場景下渲染的 DOM 太多,渲染本身的壓力很大。優化後,即使 10000 條數據,在滾動情況下的 fps 也能有 30 多,在非滾動情況下可以達到 60 滿幀。

之所以有這個差異,是因為虛擬滾動的實現方式:是只渲染視口內的 DOM。這樣總共渲染的 DOM 數量就很少了,自然性能就會好很多。

虛擬滾動組件也是 Guillaume Chau 寫的,感興趣的同學可以去研究它的源碼實現。它的基本原理就是監聽滾動事件,動態更新需要顯示的 DOM 元素,計算出它們在視圖中的位移。

虛擬滾動組件也並非沒有成本,因為它需要在滾動的過程中實時去計算,所以會有一定的 script 執行的成本。因此如果列表的數據量不是很大的情況,我們使用普通的滾動就足夠了。

總結

通過這篇文章,我希望你能了解到 Vue.js 的九種性能優化技巧,並能運用到實際的開發項目中。除了上述技巧之外,還有懶加載圖片、懶加載組件、異步組件等等常用的性能優化手段。

在做性能優化前,我們需要分析性能的瓶頸在哪,才能因地制宜。另外,性能優化都需要數據支撐的,你在做任何性能優化前,需要先採集優化前的數據,這樣優化後才能夠通過數據對比看到優化的效果。

希望你在日後的開發過程中,不再只滿足於實現需求,寫每一行代碼的時候,都能思考它可能產生的性能方面的影響。

參考資料

[1] vue-9-perf-secrets slidse:https://slides.com/akryum/vueconfus-2019

[2] vue-9-perf-secrets 分享演講視頻:https://www.vuemastery.com/conferences/vueconf-us-2019/9-performance-secrets-revealed/

[3] vue-9-perf-secrets 項目源碼:https://github.com/Akryum/vue-9-perf-secrets

[4] vue-9-perf-secrets 在線演示地址:https://vue-9-perf-secrets.netlify.app/

[5] vue-9-perf-secrets 討論 issue:https://github.com/Akryum/vue-9-perf-secrets/issues/1

[6] vue-virtual-scroller 項目源碼:https://github.com/Akryum/vue-virtual-scroller


1.關注「前端從進階到入院」,獲取我分類整理的原創精選面試熱點文章。

2. 加我好友,拉你進氛圍賊好的前端進階討論群,2021 陪你一起度過。

在看、轉發是最好的支持~


相關焦點

  • 推薦收藏,揭秘 Vue.js 九個性能優化技巧
    這篇文章主要參考了 Vue.js 核心成員 Guillaume Chau 在 19 年美國的 Vue conf 分享的主題:9 Performance secrets revealed,分享中提到了九個 Vue.js 性能優化的技巧。
  • 揭秘 Vue.js 九個性能優化技巧(黃軼老師寫的真的好,不看吃虧)
    這篇文章主要參考了 Vue.js 核心成員 Guillaume Chau 在 19 年美國的 Vue conf 分享的主題:9 Performance secrets revealed,分享中提到了九個 Vue.js 性能優化的技巧。
  • SPA單頁面應用優化VUE性能優化
    Spa單頁面應用比如vue、react、angular都是屬於單頁面應用,那麼如何優化呢?咱們拿vue舉例。來做優化,webpack能做哪些優化呢?/a.js'),讓它的 JavaScritp 被執行。那麼require.ensure如何在vue中使用呢?require.ensure主要是在vue的路由中使用,如果不使用代碼分割隨著頁面的增多build之後app.727c5a981063de8a5ac8.js會越來越大。
  • Vue.js最佳實踐(五招讓你成為Vue.js大師)
    如果有人需要Vue.js入門系列的文章可以在評論區告訴我,有空就給你們寫。對大部分人來說,掌握Vue.js基本的幾個API後就已經能夠正常地開發前端網站。但如果你想更加高效地使用Vue來開發,成為Vue.js大師,那下面我要傳授的這五招你一定得認真學習一下了。
  • 「Vue.js開發連載一」Vue.js簡介
    Vue.js的目標是通過儘可能簡單的API實現響應的數據綁定和組合的視圖組件。Vue.js自身不是一個全能框架——它只聚焦於視圖層。因此它非常容易學習,非常容易與其它庫或已有項目整合。另一方面,在與相關工具和支持庫一起使用時,Vue.js也能完美地驅動複雜的單頁應用。
  • 【項目推薦】Vue.js
    作者是尤雨溪,寫下這篇文章時 vue.js版本為 1.0.7 。我推薦使用 sublime text 作為編輯器,關於這個編輯器可以看我這篇文章。 </div> </div> </div></body></html>當然你也可以在 github 上 clone 最新的版本並作為單文件引入,或者使用 CDN:http://cdn.jsdelivr.net/vue/1.0.7/vue.min.js
  • Vue.js布局
    動態Vue.js布局組件前言vue.js是漸進增強的視圖庫,可以作為.html頁面部分使用,也可以結合vue-router、vuex、axios用來構建單頁面或多頁面應用。
  • 5招讓你成為Vue.js大師
    如果有人需要Vue.js入門系列的文章可以在評論區告訴我,有空就給你們寫。對大部分人來說,掌握Vue.js基本的幾個API後就已經能夠正常地開發前端網站。但如果你想更加高效地使用Vue來開發,成為Vue.js大師,那下面我要傳授的這五招你一定得認真學習一下了。
  • 【分享】Vue.js新手入門指南
    對於vue.js的Virtual DOM,目前業界有著褒貶不一的評價。它是一個vue.js的腳手架工具。說白了就是一個自動幫你生成好項目目錄,配置好Webpack,以及各種依賴包的工具,它可以通過npm install vue-cli -g的方式安裝,後面的-g表示全局安裝的意思,意味著你可以打開命令行之後直接通過vue命令調用它。15.我該不該學Vue.js?
  • 10 個實用的 Vue.js 工具和庫
    Gridsome 提供了一些開箱即用的最佳實踐,如代碼分割、資產優化、漸進式圖像和連結預取等。所以 Gridsome 用起來很快,而且對 PWA 支持完善,對 SEO 也很友好。Vuex( https://vuex.vuejs.org/ )5、NuxtNuxt 是常用的服務端渲染(SSR)方法。這個框架簡潔而直觀,可用來構建各種應用程式。它也是模塊化的,因此你可以只使用應用程式所需的那些模塊。
  • 初步認識vue.js框架的使用
    vue.js框架是幹什麼的Vue.js 是一個JavaScriptMVVM庫,是一套構建用戶界面的漸進式框架。它是以數據驅動和組件化的思想構建的,採用自底向上增量開發的設計。相比於Angular.js,Vue.js提供了更加簡潔、更易於理解的API,使得我們能夠快速地上手並使用Vue.js。如何使用vue.js1.下載 vue.min.js 並用 <script> 標籤引入。
  • Vue.js 2.5 發布,而這個會玩的團隊已經自研出用 Vue 開發小程序的...
    如果你使用 VSCode 與超級棒的的 Vetur 擴展,你將獲得大大改進的自動完成建議,甚至在Vue組件中使用純 JavaScript 時也能獲得輸入提示! 這是因為vue-language-server是負責分析 Vue 組件的內部包,可以利用 TypeScript 編譯器來提取有關你的代碼的更多信息。
  • 揭密vue.js的神秘之處,小程序跟vue有什麼關係
    微容用的微信小程序平臺採用開發思路是前後端分離,前端採用vue.js+h5+jq開發,後端採用MVE的思路,用php開發,用vue.js構建來微信小程序可視化前端之後,微容給大家介紹下vue的來源和特徵。
  • Vue.js 框架第三版源碼公布
    10 月 5 日凌晨,Vue.js 框架的作者兼核心開發者尤雨溪公布了尚處於 Pre-Alpha 狀態的 Vue 3 源碼(https://github.com
  • CKEditor 4 編輯器已與 Vue.js 集成
    近日,CKEditor 團隊發布了與 Vue.js 框架原生集成的 CKEditor 4。只要開發者使用的框架沒有奇怪的限制,CKEditor 4 都能與其兼容。瀏覽器支持CKEditor 4 Vue 組件可在除 Internet Explorer 之外的所有受支持的瀏覽器中使用。
  • Vue.js以業務為中心的常見面試題
    在vue.js中的MVVM模式:vue.js是通過數據驅動的,vue.js實例化對象將dom和數據進行綁定,一旦綁定,dom和數據將保持同步,每當數據發生變化,dom也會隨著變化;ViewModel是Vue.js的核心,它是Vue.js的一個實例。
  • Vue.js+Node.js 移動端小米商城全棧開發
    Vue.js靈活易學而且功能強大,是最流行的且性價比也最高的前端框架,國內絕大部分公司都在使用,它的生態環境仍在生長並且它已經擁有構建各種應用所需的一切Vue全家桶的文檔 ES2015常用語法 組件化 模塊化 基於Vue的UI庫 開發環境配置基礎環境開發工具瀏覽器模擬數據接口管理平臺項目目錄結構vue
  • Vue.js 第三方常用插件
    Vue.js devtools用於開發調試Vue.js的一個必備插件。可以在Chrome中的擴展程序中直接安裝,也可以本地文件的方式安裝。2. vue-lazyload 圖片懶加載插件地址:https://github.com/hilongjw/vue-lazyloaddemo:http://hilongjw.github.io/vue-lazyload/2.1 安裝 和 使用插件cnpm install vue-lazyload --save1
  • 推薦8 個漂亮實用的 vue.js 進度條組件
    為大家精心挑選了 8 個漂亮的 Progress Bars 組件,並附上 GitHub 連結和 vue.js 代碼示例,以及Vue3 快速深入全攻略。1.easy-circular-progress一個簡單的循環進度組件,帶有計數效果。
  • Webpack 優化技巧,構建效率提升 50%
    在本文中,谷歌開發者專家 Jennifer Bland 介紹了如何應用 Webpack 減少 Vue.js 包大小的技巧,希望能給大家帶來一些啟發。我在史丹利百德公司(Stanley Black&Decker,主營工業工具及安全方案)的工業 4.0 團隊任職。我們的團隊最近為史丹利公司分布在全球的製造工廠開發了一款相當於 App Store 的產品。