日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
十個(gè)技巧!實(shí)現(xiàn)Vue.js極致性能優(yōu)化

 

創(chuàng)新互聯(lián)建站是一家集網(wǎng)站建設(shè),周寧企業(yè)網(wǎng)站建設(shè),周寧品牌網(wǎng)站建設(shè),網(wǎng)站定制,周寧網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,周寧網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

Vue是一套用于構(gòu)建用戶界面的漸進(jìn)式的JavaScript框架。它具有體積小,更高的運(yùn)行效率,雙向數(shù)據(jù)綁定,生態(tài)豐富、學(xué)習(xí)成本低等優(yōu)點(diǎn),所以Vue也被廣泛用在移動(dòng)端跨平臺(tái)框架上。接下來,我將為大家梳理10個(gè)實(shí)現(xiàn)Vue.js極致性能優(yōu)化的技巧,以供大家在實(shí)際運(yùn)用中使用。

Vue框架通過數(shù)據(jù)雙向綁定和虛擬DOM技術(shù),幫我們處理了前端開發(fā)中最臟最累的DOM操作部分,我們不再需要去考慮如何操作DOM以及如何最高效地操作DOM,但是我們?nèi)匀恍枰リP(guān)注Vue在跨平臺(tái)項(xiàng)目性能方面的優(yōu)化,使項(xiàng)目具有更高效的性能、更好的用戶體驗(yàn)。

一、v-for遍歷必須為item添加key,

且避免同時(shí)使用v-if

在列表數(shù)據(jù)進(jìn)行遍歷渲染時(shí),需要為每一項(xiàng)item設(shè)置唯一key值,方便Vue.js內(nèi)部機(jī)制精準(zhǔn)找到該條列表數(shù)據(jù)。當(dāng)state更新時(shí),新的狀態(tài)值和舊的狀態(tài)值對(duì)比,較快地定位到diff。

我們?cè)谑褂玫氖褂媒?jīng)常會(huì)使用index(即數(shù)組的下標(biāo))來作為key,但其實(shí)這是不推薦的一種使用方法。

舉個(gè)例子:

 
 
 
 
  1. var list = [ 
  2.     { 
  3.         id: 1, 
  4.         name: 'test1', 
  5.     }, 
  6.     { 
  7.         id: 2, 
  8.         name: 'test2', 
  9.     }, 
  10.     { 
  11.         id: 3, 
  12.         name: 'test3', 
  13.     }, 
  14.  
  15.  
  16. {{item.name}}
 

在最后一條數(shù)據(jù)后再加一條數(shù)據(jù):

 
 
 
 
  1. var list = [ 
  2.     { 
  3.         id: 1, 
  4.         name: 'test1', 
  5.     }, 
  6.     { 
  7.         id: 2, 
  8.         name: 'test2', 
  9.     }, 
  10.     { 
  11.         id: 3, 
  12.         name: 'test3', 
  13.     }, 
  14.     { 
  15.         id: 4, 
  16.         name: '我是在最后添加的一條數(shù)據(jù)', 
  17.     }, 

此時(shí)前三條數(shù)據(jù)直接復(fù)用之前的,新渲染最后一條數(shù)據(jù),此時(shí)用index作為key,沒有任何問題。

在中間插入一條數(shù)據(jù):

 
 
 
 
  1. var list = [ 
  2.     { 
  3.         id: 1, 
  4.         name: 'test1', 
  5.     }, 
  6.     { 
  7.         id: 4, 
  8.         name: '我是插隊(duì)的那條數(shù)據(jù)', 
  9.     }, 
  10.     { 
  11.         id: 2, 
  12.         name: 'test2', 
  13.     }, 
  14.     { 
  15.         id: 3, 
  16.         name: 'test3', 
  17.     }, 

此時(shí)更新渲染數(shù)據(jù),通過index定義的key去進(jìn)行前后數(shù)據(jù)的對(duì)比,發(fā)現(xiàn):

 
 
 
 
  1. 之前的數(shù)據(jù)                         之后的數(shù)據(jù) 
  2.  
  3.  
  4. key: 0  index: 0 name: test1     key: 0  index: 0 name: test1 
  5.  
  6.  
  7. key: 1  index: 1 name: test2     key: 1  index: 1 name: 我是插隊(duì)的那條數(shù)據(jù) 
  8.  
  9.  
  10. key: 2  index: 2 name: test3     key: 2  index: 2 name: test2 
  11.  
  12.  
  13.                                  key: 3  index: 3 name: test3 

通過上面清晰的對(duì)比,發(fā)現(xiàn)除了第一個(gè)數(shù)據(jù)可以復(fù)用之前的之外,另外三條數(shù)據(jù)都需要重新渲染。

是不是很驚奇,我明明只是插入了一條數(shù)據(jù),怎么三條數(shù)據(jù)都要重新渲染?而我想要的只是新增的那一條數(shù)據(jù)新渲染出來就行了。

最好的辦法是使用數(shù)組中不會(huì)變化的那一項(xiàng)作為key值,對(duì)應(yīng)到項(xiàng)目中,即每條數(shù)據(jù)都有一個(gè)唯一的id,來標(biāo)識(shí)這條數(shù)據(jù)的唯一性;使用id作為key值,我們?cè)賮韺?duì)比一下向中間插入一條數(shù)據(jù),此時(shí)會(huì)怎么去渲染。

 
 
 
 
  1. 之前的數(shù)據(jù)                               之后的數(shù)據(jù) 
  2.  
  3.  
  4. key: 1  id: 1 index: 0 name: test1     key: 1  id: 1 index: 0  name: test1 
  5.  
  6.  
  7. key: 2  id: 2 index: 1 name: test2     key: 4  id: 4 index: 1  name: 我是插隊(duì)的那條數(shù)據(jù) 
  8.  
  9.  
  10. key: 3  id: 3 index: 2 name: test3     key: 2  id: 2 index: 2  name: test2 
  11.  
  12.  
  13.                                        key: 3  id: 3 index: 3  name: test3 

現(xiàn)在對(duì)比發(fā)現(xiàn)只有一條數(shù)據(jù)變化了,就是id為4的那條數(shù)據(jù),因此只要新渲染這一條數(shù)據(jù)就可以了,其他都是就復(fù)用之前的。

總結(jié) :所以一句話,key的作用主要是為了高效的更新虛擬DOM。另外Vue中在使用相同標(biāo)簽名元素的過渡切換時(shí),也會(huì)使用到key屬性,其目的也是為了讓Vue可以區(qū)分它們,否則Vue只會(huì)替換其內(nèi)部屬性而不會(huì)觸發(fā)過渡效果。

v-for遍歷避免同時(shí)使用v-if , v -for比v-if優(yōu)先級(jí)高,如果每一次都需要遍歷整個(gè)數(shù)組,將會(huì)影響速度,尤其是當(dāng)之需要渲染很小一部分的時(shí)候,必要情況下應(yīng)該替換成computed屬性。

二、長列表性能優(yōu)化

Vue會(huì)通過Object.defineProperty對(duì)數(shù)據(jù)進(jìn)行劫持,來實(shí)現(xiàn)視圖響應(yīng)數(shù)據(jù)的變化,然而有些時(shí)候我們的組件就是純粹的數(shù)據(jù)展示,不會(huì)有任何改變,我們就不需要Vue來劫持我們的數(shù)據(jù),在大量數(shù)據(jù)展示的情況下,這能夠很明顯的減少組件初始化的時(shí)間,那如何禁止Vue劫持我們的數(shù)據(jù)呢?可以通過Object.freeze方法來凍結(jié)一個(gè)對(duì)象,一旦被凍結(jié)的對(duì)象就再也不能被修改了。

 
 
 
 
  1. export default { 
  2.   data: () => ({ 
  3.     users: {} 
  4.   }), 
  5.  
  6.  
  7.   async created() { 
  8.     const users = await axios.get("/api/users"); 
  9.     this.users = Object.freeze(users); 
  10.   } 
  11. }; 

三、Vue組件中的data是函數(shù)而不是對(duì)象

 
 
 
 
  1. export default { 
  2.   data() { 
  3.     // data是一個(gè)函數(shù),data: function() {}的簡(jiǎn)寫 
  4.     return { 
  5.       // 頁面要初始化的數(shù)據(jù) 
  6.       name: 'bartonwang', 
  7.     }; 
  8.   }, 
  9. }; 

而非如下所示:

 
 
 
 
  1. export default { 
  2.   data: { 
  3.     // data是一個(gè)對(duì)象 
  4.     name: 'bartonwang', 
  5.   }, 
  6. }; 

當(dāng)一個(gè)組件被定義,data必須聲明為返回一個(gè)初始數(shù)據(jù)對(duì)象的函數(shù),因?yàn)榻M件可能被用來創(chuàng)建多個(gè)實(shí)例,復(fù)用在多個(gè)頁面。

如果data是一個(gè)純碎的對(duì)象,則所有的實(shí)例將共享引用同一份data數(shù)據(jù)對(duì)象,無論在哪個(gè)組件實(shí)例中修改data,都會(huì)影響到所有的組件實(shí)例。

如果data是函數(shù),每次創(chuàng)建一個(gè)新實(shí)例后,調(diào)用data函數(shù),從而返回初始數(shù)據(jù)的一個(gè)全新副本數(shù)據(jù)對(duì)象。

這樣每復(fù)用一次組件,會(huì)返回一份新的data數(shù)據(jù),類似于給每個(gè)組件實(shí)例創(chuàng)建一個(gè)私有的數(shù)據(jù)空間,讓各個(gè)組件的實(shí)例各自獨(dú)立,互不影響,保持低耦合。

四、Vue鉤子函數(shù)之鉤子事件hookEvent

監(jiān)聽組件簡(jiǎn)化代碼

用法:

  1. 通過$on(eventName, eventHandler) 偵聽一個(gè)事件。

  2. 通過$once(eventName,eventHandler) 一次性偵聽一個(gè)事件。

  3. 通過$off(eventName, eventHandler) 停止偵聽一個(gè)事件。

通常實(shí)現(xiàn)一個(gè)定時(shí)器的調(diào)用與銷毀我可能會(huì)以以下方式實(shí)現(xiàn):

 
 
 
 
  1. export default{ 
  2.   data(){ 
  3.     timer:null  // 需要?jiǎng)?chuàng)建實(shí)例 
  4.   }, 
  5.  
  6.  
  7.   mounted(){ 
  8.       this.timer = setInterval(()=>{ 
  9.       //具體執(zhí)行內(nèi)容 
  10.       console.log('1'); 
  11.     },1000); 
  12.   } 
  13.  
  14.  
  15.   beforeDestory(){ 
  16.     clearInterval(this.timer); 
  17.     this.timer = null; 
  18.   } 

這種方法存在的問題是:

vue實(shí)例中需要有這個(gè)定時(shí)器的實(shí)例,感覺有點(diǎn)多余。創(chuàng)建的定時(shí)器代碼和銷毀定時(shí)器的代碼沒有放在一起,不容易維護(hù),通常很容易忘記去清理這個(gè)定時(shí)器。

使用$on(‘hook:’)監(jiān)聽beforeDestory生命周期可以避免該問題, 并且因?yàn)橹恍枰O(jiān)聽一次,所以使用$once進(jìn)行注冊(cè)監(jiān)聽。

 
 
 
 
  1. export default{ 
  2.   methods:{ 
  3.     fn(){ 
  4.       const timer = setInterval(()=>{ 
  5.         console.log('1'); 
  6.       },1000); 
  7.  
  8.  
  9.       this.$once('hook:beforeDestory',()=>{ // 監(jiān)聽一次即可 
  10.         clearInterval(timer); 
  11.         timer = null; 
  12.       }) 
  13.     } 
  14.   } 

五、組件懶加載

在單頁應(yīng)用中,如果沒有應(yīng)用懶加載,運(yùn)用webpack打包后的文件將會(huì)異常地大,造成進(jìn)入首頁時(shí)需要加載的內(nèi)容過多,延時(shí)過長,不利于用戶體驗(yàn),而運(yùn)用懶加載則可以將頁面進(jìn)行劃分,需要的時(shí)候加載頁面,可以有效的分擔(dān)首頁所承擔(dān)的加載壓力,減少首頁加載用時(shí)。

Vue.js 2.0組件級(jí)懶加載方案:

  • 支持組件可見或即將可見時(shí)懶加載

  • 支持組件延時(shí)加載

  • 支持加載真實(shí)組件前展示骨架組件,提高用戶體驗(yàn)

  • 支持真實(shí)組件代碼分包異步加載

安裝:

npm install@xunlei/vue-lazy-component

在組件中實(shí)現(xiàn)局部注冊(cè)組件:

 
 
 
 
  1. import { component as VueLazyComponent } from '@xunlei/vue-lazy-component' 
  2.  
  3.  
  4. export default { 
  5.   components: { 
  6.     'vue-lazy-component': VueLazyComponent 
  7.   } 

需要懶加載的組件將其包裹在vue-lazy-component中,slot值為skeleton指的是在懶加載過程中顯示的加載狀態(tài)組件。

 
 
 
 
  1.  
  2.        
  3.        
  4.        
  5.        
  6.        
  7.  

六、非響應(yīng)式數(shù)據(jù)

初始化時(shí),Vue會(huì)對(duì)data做getter、setter改造。在Vue的文檔中介紹數(shù)據(jù)綁定和響應(yīng)時(shí),特意標(biāo)注了對(duì)于經(jīng)過Object.freeze()方法的對(duì)象無法進(jìn)行更新響應(yīng)。

性能提升對(duì)比

在基于Vue的一個(gè)big table benchmark里,可以看到在渲染一個(gè)一個(gè)1000x10的表格的時(shí)候,開啟Object.freeze()前后重新渲染的對(duì)比。

開啟優(yōu)化之前 :

開啟優(yōu)化之后 :

在這個(gè)例子里,使用了Object.freeze()比不使用快了4倍。

為什么Object.freeze()的性能會(huì)更好, 不使用Object.freeze()的CPU開銷?

使用Object.freeze()的CPU開銷:

對(duì)比可以看出,使用了Object.freeze()之后,減少了observer的開銷。

七、不要將所有的數(shù)據(jù)都放到data中

data中的數(shù)據(jù)都會(huì)增加getter和setter,又會(huì)收集watcher,這樣還占內(nèi)存。不需要響應(yīng)式的數(shù)據(jù)我們可以定義在實(shí)例上。

八、v-for元素綁定事件代理

事件代理作用主要是2個(gè):

  1. 將事件處理程序代理到父節(jié)點(diǎn),減少內(nèi)存占用率。

  2. 動(dòng)態(tài)生成子節(jié)點(diǎn)時(shí)能自動(dòng) 綁定事件處理程序到父節(jié)點(diǎn)。

  • 不使用事件代理,每個(gè)span節(jié)點(diǎn)綁定一個(gè)click事件,并指向同一個(gè)事件處理程序:

  •   
      
      
      
    1.  
    2.       
    3.         v-for="(item,index) of 100000"  
    4.         :key="index"  
    5.         @click="handleClick"> 
    6.         {{item}} 
    7.        
    8.  
 
  • 不使用事件代理,每個(gè)span節(jié)點(diǎn)綁定一個(gè)click事件,并指向不同的事件處理程序

  •   
      
      
      
    1.  
    2.       
    3.         v-for="(item,index) of 100000"  
    4.         :key="index"  
    5.         @click="function () {}"> 
    6.         {{item}} 
    7.        
    8.   
 
  • 使用事件代理

  •   
      
      
      
    1.  
    2.       
    3.         v-for="(item,index) of 100000"   
    4.         :key="index"> 
    5.         {{item}} 
    6.        
    7.  
 

可以看到使用事件代理無論是監(jiān)聽器數(shù)量和內(nèi)存占用率都比前兩者要少,同時(shí)對(duì)比3個(gè)圖中監(jiān)聽器的數(shù)量并沒有發(fā)現(xiàn)Vue會(huì)自動(dòng)做事件代理,但是一般給v-for綁定事件時(shí),都會(huì)讓節(jié)點(diǎn)指向同一個(gè)事件處理程序(第二種情況可以運(yùn)行,但是eslint會(huì)警告),一定程度上比每生成一個(gè)節(jié)點(diǎn)都綁定一個(gè)不同的事件處理程序性能好,但是監(jiān)聽器的數(shù)量仍不會(huì)變,所以使用事件代理會(huì)更好一點(diǎn)。

代碼使用:

 
 
 
 
  1.  
  2.       {{item}}
  3.  
  4.   
  5.  
  6.  
  7. meths(e) { 
  8.       if (e.target.nodeName.toLowerCase() === 'li') { 
  9.         console.log(e.target.innerHTML) 
  10.         console.log(e.target.dataset) 
  11.       } 
  12.  
  13.  

九、函數(shù)式組件

函數(shù)式組件是無狀態(tài),它無法實(shí)例化,沒有任何的生命周期和方法。創(chuàng)建函數(shù)式組件也很簡(jiǎn)單,只需要在模板添加functional聲明即可。一般適合只依賴于外部數(shù)據(jù)的變化而變化的組件,因其輕量,渲染性能也會(huì)有所提高。

組件需要的一切都是通過context參數(shù)傳遞。它是一個(gè)上下文對(duì)象,具體屬性查看文檔。這里props是一個(gè)包含所有綁定屬性的對(duì)象。

函數(shù)式組件

十、函數(shù)式組件provide和inject組件通信

痛點(diǎn):常用的父子組件通信方式都是父組件綁定要傳遞給子組件的數(shù)據(jù),子組件通過props屬性接收,一旦組件層級(jí)變多時(shí),采用這種方式一級(jí)一級(jí)傳遞值非常麻煩,而且代碼可讀性不高,不便后期維護(hù)。

Vue提供了provide和inject幫助我們解決多層次嵌套嵌套通信問題。在provide中指定要傳遞給子孫組件的數(shù)據(jù),子孫組件通過inject注入祖父組件傳遞過來的數(shù)據(jù),可以輕松實(shí)現(xiàn)跨級(jí)訪問父組件的數(shù)據(jù)。

provide:是一個(gè)對(duì)象,或者是一個(gè)返回對(duì)象的函數(shù)。里面呢就包含要給子孫后代的東西,也就是屬性和屬性值。 注意:子孫層的provide會(huì)掩蓋祖父層provide中相同key的屬性值 。

inject:一個(gè)字符串?dāng)?shù)組,或者是一個(gè)對(duì)象。屬性值可以是一個(gè)對(duì)象,包含from和default默認(rèn)值,from是在可用的注入內(nèi)容中搜索用的key (字符串或Symbol),意思就是祖父多層provide提供了很多數(shù)據(jù),from屬性指定取哪一個(gè)key;default指定默認(rèn)值。

從上面這個(gè)例子可以看出,只要在父組件中調(diào)用了,那么在這個(gè)父組件生效的生命周期內(nèi),所有的子組件都可以調(diào)用inject來注入父組件中的值。

在使用場(chǎng)景中,肯定是希望父組件的數(shù)據(jù)一旦發(fā)生改變,子孫組件獲取到的也是父組件更新后的數(shù)據(jù)。那么,怎么實(shí)現(xiàn)父組件與子孫組件所綁定的數(shù)據(jù)動(dòng)態(tài)響應(yīng)呢?

 
 
 
 
  1. -------------------parent.vue---------------------- 
  2.  
  3.  
  4. provide(){ 
  5.  
  6.  
  7.     return { 
  8.  
  9.  
  10.    // keyName: {name:this.name}, // value 是對(duì)象才能實(shí)現(xiàn)響應(yīng)式,也就是引用類型 
  11.  
  12.  
  13.       keyName: this.changeValue // 通過函數(shù)的方式也可以[注意,這里是把函數(shù)作為value,而不是this.changeValue()] 
  14.  
  15.  
  16.    // keyName: 'test' value 如果是基本類型,就無法實(shí)現(xiàn)響應(yīng)式 
  17.  
  18.  
  19.     } 
  20.   }, 
  21.  
  22.  
  23. data(){ 
  24.  
  25.  
  26.   return { 
  27.       name:'張三' 
  28.   } 
  29.    
  30.   }, 
  31.  
  32.  
  33.   methods: { 
  34.  
  35.  
  36.   changeValue(){ 
  37.       this.name = '改變后的名字-李四' 
  38.    } 
  39.     
  40.   }   
  41.  
  42.  
  43.   -------------grandson.vue----------------- 
  44.  
  45.  
  46.   inject:['keyName'] 
  47.   create(){ 
  48.      console.log(this.keyName) // 改變后的名字-李四 

新聞名稱:十個(gè)技巧!實(shí)現(xiàn)Vue.js極致性能優(yōu)化
地址分享:http://m.5511xx.com/article/cdpddci.html