您好,登錄后才能下訂單哦!
本篇內容介紹了“Vue.js中的性能陷阱是什么”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
調查性能下降的原因
我首先使用 Lighthouse 進行了快速測試。所幸 Firefox 為此提供了一個瀏覽器插件:
https://addons.mozilla.org/en-US/firefox/addon/google-lighthouse/
下面就是我得到的結果。
89%的數字挺不錯的。實際上,與許多流行的網站相比,這個表現相當出色。這個測試指出了一些潛在問題,例如速度指數和第一次有意義且有內容的繪制步驟等。從理論上講,解決這些問題會進一步提高分數,但不一定能解決應用面臨的嚴重性能問題。
我們的游戲中有一些圖像和音頻素材資源,但是兩者都不至于讓游戲卡死在那里。我們也可以對這些已經優化過的資源再過度優化一遍,但這可能根本就無濟于事。
這個測試無法讓我們真正找出可能導致這一性能問題的原因。于是我開始想:“該不會是 Vue 的問題吧?”這種想法會冒出來也沒什么理由,但要是不檢查一下就是蠢了。我檢查了已部署站點的控制臺,結果空白一片。但警告往往不會在生產中顯示。當我在本地進行相同操作時,一堆 Vue 警告讓我吃了一驚。
像大多數開發人員一樣,我對控制臺警告沒那么在意,覺得它們只是警告,而不代表錯誤;所以我一般會把注意力集中在其他地方。或許消除這些警告可以解決我的生產問題,我決定深入研究每個問題并修復它們。
所有這些警告均來自我創建的、用來顯示名為 Cards.vue 選項的組件,因此這個組件可能需要大量重寫。
我決定按順序解決這些控制臺警告。
> [Vue warn]: Avoid using non-primitive value as key, use string/number value instead. found in ---> <Cards> at src/components/Cards.vue
Vue.js 有很多指令,讓我們能更直觀地使用框架,比如說 v-for 就可以快速將數組渲染為列表。使用它時,我們需要一個 :key 才能有效地重渲染組件。但我們將一個對象用作了一個鍵,這是非原始值,因此導致了這個錯誤。我決定將 index.description 用作一個新鍵,因為它是一個字符串,并且在值發生更改時可以更好地重新渲染。
> [Vue warn]: Duplicate keys detected: '[object Object]'. This may cause an update error. found in ---> <Cards> at src/components/Cards.vue
將 :key 更改為一個字符串(index.description)來解決上一個錯誤,就能解決這個重復鍵的錯誤。我們只能將字符串類型寫入 DOM,因此當我們傳遞一個要渲染的對象時,該對象將轉換為等效的字符串(即 [object Object]);并且因為這以前是我們的鍵,所以每個對象都將轉換為 [object Object](除非對象有不同的值),進而會出現重復鍵警告。現在既然鍵不是對象,警告就會消失,效率也會提升。
> [Vue warn]: You may have an infinite update loop in a component render function. found in ---> <Cards> at src/components/Cards.vue
就一個非常模糊的警告來說,這個警告似乎是最重要的:無限循環意味著內存消耗。這條消息并沒有告訴我們可能出了什么問題,但它確實暗示了問題與組件中的 render 函數有關。也許是因為我們寫的代碼比較取巧,因此觸發了不間斷的更新,并占用了大量的計算能力,以至于使瀏覽器和設備崩潰。
這條警告至少告訴我們要檢查 Cards.vue,所以我的第一個想法是檢查組件中的反應屬性,因為這可能會導致錯誤。反應屬性在更改后會觸發重新渲染。
我們正在顯示 index.days 和 index.description 中的數據。但我們不會更改這些數據,我們從 cardInfo 數組獲得 index。
> v-for="index in cardInfo.sort(() => Math.random() - 0.7).slice(0,4)"
我們使用這段代碼對數組中的元素進行隨機排序,然后將前四個元素顯示為玩家選擇的選項。當用戶單擊一個選項時將調用 effects() 函數,它除了會計算一個動作如何影響游戲狀態外,還使用 cardInfo 上的拼接原型刪除前四個元素。
在 Vue 這種使用虛擬 DOM 的框架里,用上諸如 cardInfo 之類的反應屬性后,每當數據屬性的值更改時都會觸發重新渲染。在我們的應用里,我們會直接使用 sort() 原型來更改它,然后刪除元素來重新排序。所有這些都會觸發“無限”的重新渲染,從而引發警告。
我決定更改數據過濾的邏輯,并停止對反應屬性 cardInfo 的多次更改。我安裝了 lodash.shuffle 并定義了一個計算屬性 shuffledList(),它將創建一個名為 list 的 cardInfo 副本。我對其應用了隨機排序操作,并返回了一個“frozen”結果,然后拆分開來顯示四張卡片。我們使用了 Object.freeze(),它將使我們返回的對象不可變,從而完全停止了所有重新渲染操作。
至此,問題解決了。
掉進框架的坑
老實說,當我剛開始調查性能下降原因的時候,還覺得我肯定要優化很多資源才能解決問題。最后這個結果說明,在使用許多框架抽象時我們都必須非常小心——特別是在 Vue 中更是如此,只有在必要時才使用某條指令,而且用法一定不能出錯,因為它們絕對有自己的代價。
這還讓我開始思考自己做過的其他工作,其中應用程序可能會因為框架而出現不必要的性能問題。大多數現代的前端框架都有很多抽象,使我們能更輕松地為 Web 制作應用程序。但我們應該牢記一點,那就是使用這些東西可能會引發潛在的性能問題。
我經常使用 Vue.js,所以決定探索一些我以前用過的指令,以前我用這些指令的時候完全沒考慮過它們可能對應用程序帶來的性能影響。其中有三條非常流行的指令進入了我的視線。
1. v-if 和 v-show
這兩條指令都是用來有條件地渲染元素的,但是它們背后的工作機制卻大不相同,因此用法也大相徑庭。v-if 一開始不會渲染組件,而只在條件為真時才渲染組件。這意味著當你多次切換組件的可見性時,就會不斷重新渲染。如果你要多次更改組件的可見性,那就不要使用這個功能。這會影響你的性能。
v-show 是一個很好的替代品。不管你是否啟用 CSS 都會渲染你的組件,但是只會根據條件是 true 還是 false 來決定組件是否可見。這種方法確實有其缺點,因為它不會將非必要組件的渲染推遲到你需要它們在屏幕上實際出現的時候。如果你的初始渲染沒那么復雜,那么它就很合適。
2. v-for
這條指令通常用來從數組中渲染列表。它有一個特殊的語法,形式為 item in list,其中 list 是源數據數組,而 item 是要迭代的數組元素的別名。默認情況下,Vue 在源數據數組上添加 watchers,每當發生更改時它就會觸發重新渲染。這種持續的重新渲染可能會對應用程序性能產生不利影響。如果你只想可視化對象,那么 Object.freeze() 是一個很好的解決方案,可以大大提高性能。但是請務必記住,你將無法更新組件或編輯對象數據。
在這個研究過程中我還意識到,Lighthouse 可能檢查的是以更直接的方式影響用戶體驗的應用性能指標,所以接下來我的疑問就是如何跟蹤服務器上的應用程序性能。
“Vue.js中的性能陷阱是什么”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。