Vue常用性能優化


Vue常用性能優化

Vue常用的一些優化方式,主要是在構建項目過程需要注意的方面。

編碼優化

避免響應所有數據

不要將所有的數據都放到data中,data中的數據都會增加gettersetter,並且會收集watcher,這樣還占內存,不需要響應式的數據我們可以直接定義在實例上。

<template>
    <view>

    </view>
</template>

<script>
    export default {
        components: {},
        data: () => ({
            
        }),
        beforeCreate: function(){
            this.timer = null;
        }
    }
</script>

<style scoped>
</style>

函數式組件

函數組是一個不包含狀態和實例的組件,簡單的說,就是組件不支持響應式,並且不能通過this關鍵字引用自己。因為函數式組件沒有狀態,所以它們不需要像Vue的響應式系統一樣需要經過額外的初始化,這樣就可以避免相關操作帶來的性能消耗。當然函數式組件仍然會對相應的變化做出響應式改變,比如新傳入新的props,但是在組件本身中,它無法知道數據何時發生了更改,因為它不維護自己的狀態。很多場景非常適合使用函數式組件:

  • 一個簡單的展示組件,也就是所謂的dumb組件。例如buttonspillstagscards等,甚至整個頁面都是靜態文本,比如About頁面。
  • 高階組件,即用於接收一個組件作為參數,返回一個被包裝過的組件。
  • v-for循環中的每項通常都是很好的候選項。

區分computed和watch使用場景

computed是計算屬性,依賴其它屬性值,並且computed的值有緩存,只有它依賴的屬性值發生改變,下一次獲取computed的值時才會重新計算computed的值。
watch更多的是觀察的作用,類似於某些數據的監聽回調,每當監聽的數據變化時都會執行回調進行后續操作。
當我們需要進行數值計算,並且依賴於其它數據時,應該使用computed,因為可以利用computed的緩存特性,避免每次獲取值時,都要重新計算。當我們需要在數據變化時執行異步或開銷較大的操作時,應該使用watch,使用watch選項允許我們執行異步操作,限制我們執行該操作的頻率,並在我們得到最終結果前,設置中間狀態。

v-for添加key且避免同時使用v-if

  • v-for遍歷必須為item添加key,且盡量不要使用index而要使用唯一id去標識item,在列表數據進行遍歷渲染時,設置唯一key值方便Vue.js內部機制精准找到該條列表數據,當state更新時,新的狀態值和舊的狀態值對比,較快地定位到diff
  • v-for遍歷避免同時使用v-ifv-forv-if優先級高,如果每一次都需要遍歷整個數組,將會影響速度。

區分v-if與v-show使用場景

  • 實現方式: v-if是動態的向DOM樹內添加或者刪除DOM元素,v-show是通過設置DOM元素的display樣式屬性控制顯隱。
  • 編譯過程: v-if切換有一個局部編譯卸載的過程,切換過程中合適地銷毀和重建內部的事件監聽和子組件,v-show只是簡單的基於CSS切換。
  • 編譯條件: v-if是惰性的,如果初始條件為假,則什么也不做,只有在條件第一次變為真時才開始局部編譯, v-show是在任何條件下都被編譯,然后被緩存,而且DOM元素保留。
  • 性能消耗: v-if有更高的切換消耗,v-show有更高的初始渲染消耗。
  • 使用場景: v-if適合條件不太可能改變的情況,v-show適合條件頻繁切換的情況。

長列表性能優化

Vue會通過Object.defineProperty對數據進行劫持,來實現視圖響應數據的變化,然而有些時候我們的組件就是純粹的數據展示,不會有任何改變,我們就不需要Vue來劫持我們的數據,在大量數據展示的情況下,這能夠很明顯的減少組件初始化的時間,可以通過Object.freeze方法來凍結一個對象,一旦被凍結的對象就再也不能被修改了。對於需要修改的長列表的優化大列表兩個核心,一個分段一個區分,具體執行分為:僅渲染視窗可見的數據、進行函數節流、 減少駐留的VNodeVue組件,不使用顯示的子組件slot方式,改為手動創建虛擬DOM來切斷對象引用。

export default {
  data: () => ({
      users: {}
  }),
  async created() {
      const users = await axios.get("/api/users");
      this.users = Object.freeze(users);
  }
};

路由懶加載

Vue是單頁面應用,可能會有很多的路由引入,這樣使用webpcak打包后的文件很大,當進入首頁時,加載的資源過多,頁面會出現白屏的情況,不利於用戶體驗。如果我們能把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應的組件,這樣就更加高效。對於Vue路由懶加載的方式有Vue異步組件、動態importwebpack提供的require.ensure,最常用的就是動態import的方式。

{
  path: "/example",
  name: "example",
  //打包后,每個組件單獨生成一個chunk文件
  component: () => import("@/views/example.vue")
}

服務端渲染SSR

如果需要優化首屏加載速度並且首屏加載速度是至關重要的點,那么就需要服務端渲染SSR,服務端渲染SSR其實是優缺點並行的,需要合理決定是否真的需要服務端渲染。

優點

  • 更好的SEO,由於搜索引擎爬蟲抓取工具可以直接查看完全渲染的頁面,如果SEO對站點至關重要,而頁面又是異步獲取內容,則可能需要服務器端渲染SSR解決此問題。
  • 更快的內容到達時間time-to-content,特別是對於緩慢的網絡情況或運行緩慢的設備,無需等待所有的JavaScript都完成下載並執行,用戶將會更快速地看到完整渲染的頁面,通常可以產生更好的用戶體驗,並且對於那些內容到達時間time-to-content與轉化率直接相關的應用程序而言,服務器端渲染SSR至關重要。

缺點

  • 開發條件所限,瀏覽器特定的代碼,只能在某些生命周期鈎子函數lifecycle hook中使用,一些外部擴展庫external library可能需要特殊處理,才能在服務器渲染應用程序中運行。
  • 涉及構建設置和部署的更多要求,與可以部署在任何靜態文件服務器上的完全靜態單頁面應用程序SPA不同,服務器渲染應用程序,通常需要處於Node.js server運行環境。
  • 更大的服務器端負載,在Node.js中渲染完整的應用程序,顯然會比僅僅提供靜態文件的server更加大量占用CPU資源CPU-intensive-CPU密集型,因此如果預料在高流量環境high traffic下使用,需要准備相應的服務器負載,並明智地采用緩存策略。

使用keep-alive組件

當在組件之間切換的時候,有時會想保持這些組件的狀態,以避免反復重渲染導致的性能等問題,使用<keep-alive>包裹動態組件時,會緩存不活動的組件實例,而不是銷毀它們。重新創建動態組件的行為通常是非常有用的,但是在有些情況下我們更希望那些標簽的組件實例能夠被在它們第一次被創建的時候緩存下來,此時使用<keep-alive>包裹組件即可緩存當前組件實例,將組件緩存到內存,用於保留組件狀態或避免重新渲染,和<transition>相似它,其自身不會渲染一個DOM元素,也不會出現在組件的父組件鏈中。

<keep-alive>
    <component v-bind:is="currentComponent" class="tab"></component>
</keep-alive>

打包優化

模板預編譯

當使用DOM內模板或JavaScript內的字符串模板時,模板會在運行時被編譯為渲染函數,通常情況下這個過程已經足夠快了,但對性能敏感的應用還是最好避免這種用法。預編譯模板最簡單的方式就是使用單文件組件——相關的構建設置會自動把預編譯處理好,所以構建好的代碼已經包含了編譯出來的渲染函數而不是原始的模板字符串。如果使用webpack,並且喜歡分離JavaScript和模板文件,可以使用vue-template-loader,其可以在構建過程中把模板文件轉換成為JavaScript渲染函數。

SourceMap

在項目進行打包后,會將開發中的多個文件代碼打包到一個文件中,並且經過壓縮、去掉多余的空格、babel編譯化后,最終將編譯得到的代碼會用於線上環境,那么這樣處理后的代碼和源代碼會有很大的差別,當有bug的時候,我們只能定位到壓縮處理后的代碼位置,無法定位到開發環境中的代碼,對於開發來說不好調式定位問題,因此sourceMap出現了,它就是為了解決不好調式代碼問題的,在線上環境則需要關閉sourceMap

配置splitChunksPlugins

Webpack內置了專門用於提取多個Chunk中的公共部分的插件CommonsChunkPlugin,是用於提取公共代碼的工具,CommonsChunkPlugin4.0及以后被移除,使用SplitChunksPlugin替代。

使用treeShaking

tree shaking是一個術語,通常用於描述移除JavaScript上下文中的未引用代碼dead-code,其依賴於ES2015模塊系統中的靜態結構特性,例如importexport,這個術語和概念實際上是興起於ES2015模塊打包工具rollup

第三方插件的按需引入

我們在項目中經常會需要引入第三方插件,如果我們直接引入整個插件,會導致項目的體積太大,我們可以借助babel-plugin-component,然后可以只引入需要的組件,以達到減小項目體積的目的,以項目中引入element-ui組件庫為例。

{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

import Vue from 'vue';
import { Button, Select } from 'element-ui';

Vue.use(Button)
Vue.use(Select)

每日一題

https://github.com/WindrunnerMax/EveryDay

參考

https://zhuanlan.zhihu.com/p/121000054
https://www.jianshu.com/p/f372d0e3de80
https://juejin.im/post/6844903887787278349
https://juejin.im/post/6844904189999448071
https://www.lagou.com/lgeduarticle/22278.html
https://www.cnblogs.com/mmzuo-798/p/11778044.html
https://blog.csdn.net/gtlbtnq9mr3/article/details/104889927


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM