成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android Webview中Vue初始化的性能優化

移動開發 Android
一般來說,你不需要太關心vue的運行時性能,它在運行時非常快,但付出的代價是初始化時相對較慢。在最近開發的一個Hybrid APP里,Android Webview初始化一個較重的vue頁面竟然用了1200ms ~ 1400ms,這讓我開始重視vue的初始化性能,并最終優化到200 ~ 300ms,這篇文章分享我的優化思路。

[[171575]]

 前言

一般來說,你不需要太關心vue的運行時性能,它在運行時非常快,但付出的代價是初始化時相對較慢。在最近開發的一個Hybrid APP里,Android Webview初始化一個較重的vue頁面竟然用了1200ms ~ 1400ms,這讓我開始重視vue的初始化性能,并最終優化到200 ~ 300ms,這篇文章分享我的優化思路。

性能瓶頸在哪里?

先看一下常見的vue寫法:在html里放一個app組件,app組件里又引用了其他的子組件,形成一棵以app為根節點的組件樹。

  1. <body> 
  2.     <app></app>  
  3. </body>  

而正是這種做法引發了性能問題,要初始化一個父組件,必然需要先初始化它的子組件,而子組件又有它自己的子組件。那么要初始化根標簽<app>,就需要從底層開始冒泡,將頁面所有組件都初始化完。所以我們的頁面會在所有組件都初始化完才開始顯示。

這個結果顯然不是我們要的,更好的結果是頁面可以從上到下按順序流式渲染,這樣可能總體時間增長了,但首屏時間縮減,在用戶看來,頁面打開速度就更快了。

要實現這種渲染模式,我總結了下有3種方式實現。第3種方式是我認為最合適的,也是我在項目中實際使用的優化方法。

***種:不使用根組件

這種方式非常簡單,例如:

  1. <body> 
  2.     <A></A> 
  3.     <B></B> 
  4.     <C></C> 
  5. </body>  

拋棄了根組件<app>,從而使A、B、C每一個組件初始化完都立刻展示。但根組件在SPA里是非常必要的,所以這種方式只適用小型頁面。

第二種:異步組件

異步組件在官方文檔已有說明,使用非常簡單: 

  1. <app> 
  2.     <A></A> 
  3.     <B></B> 
  4. </app>  
  1. new Vue({ 
  2.     components: { 
  3.         A: { /*component-config*/ }, 
  4.         B (resolve) { 
  5.             setTimeout(() => { 
  6.                 resolve({ /*component-config*/ }) 
  7.             }, 0); 
  8.         } 
  9.     } 
  10. })  

這里<B>組件是一個異步組件,會等到手動調用resolve函數時才開始初始化,而父組件<app>也不必等待<B>先初始化完。

我們利用setTimeout(fn, 0)將<B>的初始化放在隊列***,結果就是頁面會在<A>初始化完后立刻顯示,然后再顯示<B>。如果你的頁面有幾十個組件,那么把非首屏的組件全設成異步組件,頁面顯示速度會有明顯的提升。

你可以封裝一個簡單的函數來簡化這個過程: 

  1. function deferLoad (component, time = 0) { 
  2.     return (resolve) => { 
  3.         window.setTimeout(() => resolve(component), time
  4.     }; 
  5.  
  6. new Vue({ 
  7.     components: { 
  8.         B: deferLoad( /*component-config*/ ), 
  9.         // 100ms后渲染 
  10.         C: deferLoad( /*component-config*/, 100 ) 
  11.     } 
  12. }) 

 看起來很美好,但這種方式也有問題,考慮下這樣的結構: 

  1. <app> 
  2.     <title></title> 
  3.     <A></A> 
  4.     <title></title> 
  5.     <B></B> 
  6.     <title></title> 
  7.     <C></C> 
  8. </app>  

還是按照上面的異步組件做法,這時候就需要考慮把哪些組件設成異步的了。如果把A、B、C都設成異步的,那結果就是3個<title>會首先渲染出來,頁面渲染的過程在用戶看來非常奇怪,并不是預期中的從上到下順序渲染。

第三種:v-if 和 terminal指令

這是我推薦的一種做法,簡單有效。還是那個結構,我們給要延遲渲染的組件加上v-if:

  1. <app> 
  2.     <A></A> 
  3.     <B v-if="showB"></B> 
  4.     <C v-if="showC"></C> 
  5. </app>  
  1. new Vue({ 
  2.     data: { 
  3.         showB: false
  4.         showC: false 
  5.     }, 
  6.     created () { 
  7.         // 顯示B 
  8.         setTimeout(() => { 
  9.             this.showB = true
  10.         }, 0); 
  11.         // 顯示C 
  12.         setTimeout(() => { 
  13.             this.showC = true
  14.         }, 0); 
  15.     } 
  16. });  

這個示例寫起來略顯啰嗦,但它已經實現了我們想要的順序渲染的效果。頁面會在A組件初始化完后顯示,然后再按順序渲染其余的組件,整個頁面渲染方式看起來是流式的。

有些人可能會擔心v-if存在一個編譯/卸載過程,會有性能影響。但這里并不需要擔心,因為v-if是惰性的,只有當***次值為true時才會開始初始化。

這種寫法看起來很麻煩,如果我們能實現一個類似v-if的組件,然后直接指定多少秒后渲染,那就更好了,例如: 

  1. <app> 
  2.     <A></A> 
  3.     <B v-lazy="0"></B> 
  4.     <C v-lazy="100"></C> 
  5. </app>  

一個簡單的指令即可,不需要js端任何配合,并且可以用在普通dom上面,Nice!

在vue里,類似v-if和v-for這種是terminal指令,會在指令內部編譯組件。如果你想要自己實現一個terminal指令,需要加上terminal: true,例如: 

  1. Vue.directive('lazy', { 
  2.     terminal: true
  3.     bind () {}, 
  4.     update () {}, 
  5.     unbind () {} 
  6. });  

這是vue在1.0.19+新增的功能,由于比較冷門,文檔也沒有特別詳細的敘述,***的方式是參照著v-if和v-for的源碼來寫。

我已經為此封裝了一個terminal指令,你可以直接使用:

https://github.com/Coffcer/vu...

其他的優化點

除了組件上的優化,我們還可以對vue的依賴改造入手。初始化時,vue會對data做getter、setter改造,在現代瀏覽器里,這個過程實際上挺快的,但仍然有優化空間。

Object.freeze()是ES5新增的API,用來凍結一個對象,禁止對象被修改。vue 1.0.18+以后,不會對已凍結的data做getter、setter轉換。

如果你確保某個data不需要跟蹤依賴,可以使用Object.freeze將其凍結。但請注意,被凍結的是對象的值,你仍然可以將引用整個替換調。看下面例子:

  1. <p v-for="item in list">{{ item.value }}</p>  
  1. new Vue({ 
  2.     data: { 
  3.         // vue不會對list里的object做getter、setter綁定 
  4.         list: Object.freeze([ 
  5.             { value: 1 }, 
  6.             { value: 2 } 
  7.         ]) 
  8.     }, 
  9.     created () { 
  10.         // 界面不會有響應 
  11.         this.list[0].value = 100; 
  12.  
  13.         // 下面兩種做法,界面都會響應 
  14.         this.list = [ 
  15.             { value: 100 }, 
  16.             { value: 200 } 
  17.         ]; 
  18.         this.list = Object.freeze([ 
  19.             { value: 100 }, 
  20.             { value: 200 } 
  21.         ]); 
  22.     } 
  23. })  

后記

vue 1.0+ 的組件其實不算輕量,初始化一個組件包括依賴收集、轉換等過程,但其實有些是可以放在編譯時提前完成的。vue 2.0+ 已經在這方面做了不少的改進:分離了編譯時和運行時、提供函數組件等,可以預見,vue 2.0的性能將有很大的提升。

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2019-11-04 13:50:36

Java數組編程語言

2022-01-26 11:00:58

源碼層面Vue3

2011-06-17 15:29:44

C#對象初始化器集合初始化器

2023-10-06 20:57:52

C++聚合成員

2023-11-12 23:08:17

C++初始化

2024-01-18 11:25:11

延遲初始化技術Lazy類資源管理

2012-12-28 14:53:34

Android開發初始化窗體事件

2023-05-29 09:37:17

Vue3Vite

2011-03-16 10:52:20

2012-03-13 13:38:42

Java

2009-06-10 16:17:00

Netbeans JT初始化

2021-07-07 05:00:17

初始化源碼

2011-07-22 17:46:43

java

2023-07-13 09:13:18

Docker容器

2023-12-18 09:26:12

C++switchif

2009-09-08 09:48:34

LINQ初始化數組

2009-11-11 15:29:15

ADO初始化

2010-07-28 10:22:33

FlexApplica

2021-03-12 10:30:11

SpringMVC流程初始化

2022-07-06 10:37:45

SpringServlet初始化
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 中文字幕在线视频免费视频 | 欧美日韩一区二区在线 | 亚洲成人免费av | 精品一区国产 | av大全在线 | 亚洲一区二区三 | www.日韩| 欧美片网站免费 | 久久小视频 | 午夜视频免费在线观看 | 超碰3 | 成人一区二区三区 | 欧美午夜精品久久久久免费视 | 久久com | 97国产精品| 亚洲视频www| 国产福利91精品一区二区三区 | 国产成人99久久亚洲综合精品 | 久久久国产一区 | 欧美一区二区在线观看视频 | 午夜男人视频 | 成人亚洲精品 | 日韩美香港a一级毛片免费 国产综合av | 91五月天 | 亚洲 欧美 日韩 在线 | 精品中文在线 | 黄在线免费观看 | 亚洲国产精品日韩av不卡在线 | 亚洲午夜在线 | 三级av在线| av一区二区三区四区 | 欧美黄在线观看 | 美女国产| 精品国产乱码久久久久久牛牛 | 亚洲国产高清高潮精品美女 | 午夜精品久久久久久久久久久久 | av在线一区二区三区 | 中文av电影 | 亚洲国产成人精品女人久久久野战 | 国产精品黄色 | 91精品国产一区二区三区 |