從4個方面優化你的Vue專案
兩者的區別是:v-if不渲染DOM,v-show會預渲染DOM
除以下情況使用v-show
,其他情況儘量使用v-if
-
有預渲染需求
-
需要頻繁切換顯示狀態
2、v-for必須加上key,並避免同時使用v-if
一般我們在兩種常見的情況下會傾向於這樣做:
-
為了過濾一個列表中的專案 比如
v-for="user in users" v-if="user.isActive"
。在這種情形下,請將users
替換為一個計算屬性 (比如activeUsers
),讓其返回過濾後的列表 -
為了避免渲染本應該被隱藏的列表 比如
v-for="user in users" v-if="shouldShowUsers"
。這種情形下,請將v-if
移動至容器元素上 (比如 ul, ol)
3、事件及時銷燬
Vue元件銷燬時,會自動清理它與其它例項的連線,解綁它的全部指令及事件監聽器,但是僅限於元件本身的事件。
也就是說,在js內使用addEventListener等方式是不會自動銷燬的,我們需要在元件銷燬時手動移除這些事件的監聽,以免造成記憶體洩露,如:
created() { addEventListener('touchmove', this.touchmove, false) }, beforeDestroy() { removeEventListener('touchmove', this.touchmove, false) } 複製程式碼
首屏優化
1、圖片裁剪、使用webp
-
圖片需要裁剪,一般使用二倍圖即可
-
儘量使用webp圖片
-
如果使用了vue-lazyload外掛,可以使用以下方法一鍵替換webp(替換使用v-lazy指令的圖片)
Vue.use(VueLazyload, { error: require('./assets/img/defaultpic_small.png'), filter: { webp (listener: any, options: any) { if (!options.supportWebp) return // listener.src += '.webp' } } }); 複製程式碼
2、資源提前請求
經測試,Vue專案中各檔案的載入順序為:router.js、main.js、App.vue、[page].vue、[component].vue,如圖:

其中,router的載入時間相比於page.vue快近100ms,如果page.vue的檔案較多,時間差異會更大 所以,可以在頁面掛載、渲染的同時去請求介面資料,如在router.js中請求資料:
import Router from 'vue-router' import store from './store' store.dispatch('initAjax') 複製程式碼
3、非同步路由
使用非同步路由可以根據URL自動載入所需頁面的資源,並且不會造成頁面阻塞,較適用於移動端頁面
建議主頁面直接import,非主頁面使用非同步路由
使用方式:
{ path: '/order', component: () => import('./views/order.vue') } 複製程式碼
4、非同步元件
不需要首屏載入的元件都使用非同步元件的方式來載入(如多tab),包括需要觸發條件的動作也使用非同步元件(如彈窗) 使用方式為:v-if來控制顯示時機,引入元件的Promise即可
<template> <div> <HellowWorld v-if="showHello" /> </div> </template> <script> export default { components: { HellowWorld: () => import('../components/HelloWorld.vue') }, data() { return { showHello: false } }, methods: { initAsync() { addEventListener('scroll', (e) => { if (scrollY > 100) { this.showHello = true } }) } } } </script> 複製程式碼
5、使用輕量級外掛、非同步外掛
-
使用webpack-bundle-analyzer檢視專案所有包的體積大小,較大的外掛包儘量尋找輕量級的替代方案
-
首屏用不到的外掛、或只在特定場景才會用到的外掛使用非同步載入(如定位外掛,部分情況可以通過URL傳遞經緯度;或生成畫報外掛,需要在點選時觸發);外掛第一次載入後快取在本地,使用方式為:
// 以定位外掛為例 const latitude = getUrlParam('latitude') const longitude = getUrlParam('longitude') // 如果沒有經緯度引數,則使用定位外掛來獲取經緯度 if (!latitude || !longitude) { // 首次載入定位外掛 // webpack4寫法,若使用webpack3及以下,則await import('locationPlugin')即可 if (!this.WhereAmI) this.WhereAmI = (await import('locationPlugin')).default // do sth... } 複製程式碼
6、公用CDN
使用公用的CDN資源,可以起到快取作用,並減少打包體積
網路優化
1、減少網路請求
瀏覽器對同一時間針對同一域名下的請求有一定數量限制(一般是6個),超過限制數目的請求會被阻塞
首屏儘可能減少同域名的請求,包括介面和js;按需減少首屏的chunk.js,合併介面請求
2、合理使用preload、dns-prefetch、prefetch
-
preload具有較高的載入優先順序,它可以利用間隙時間預載入資源,將載入和執行分離開,不阻塞渲染和document的onload事件
-
每次與域名連線都需要進行DNS解析,使用dns-prefetch可以預解析域名的DNS
-
prefetch會預載入頁面將來可能用到的一些資源,優先順序較低;對首屏渲染要求較高的專案不建議使用
三者的使用方式,在head標籤中新增(vue-cli-3已經做了相應配置):
<head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <link rel="icon" href="/dist/favicon.ico" /> <!-- dns-prefetch寫法 --> <link rel="dns-prefetch" href="//www.dpfile.com" /> <title>md-config</title> <!-- preload寫法,as屬性必須 --> <link href="/dist/css/app.52dd885e.css" rel="preload" as="style" /> <link href="/dist/js/app.05faf3b5.js" rel="preload" as="script" /> <link href="/dist/js/chunk-vendors.04343b1f.js" rel="preload" as="script" /> <!-- prefetch寫法 --> <link href="/dist/js/chunk-vendors.04343b1f.js" rel="prefetch" /> </head> 複製程式碼
3、PWA
PWA支援快取HTML文件、介面(get)等,降低頁面白屏時間 這樣即使在弱網甚至斷網情況下,也能迅速展示出頁面