每種編程語(yǔ)言都有它的內(nèi)存管理機(jī)制,不同設(shè)備上可用內(nèi)存不同,分配給JS引擎可用的內(nèi)存范圍也不同。例如運(yùn)行內(nèi)存在128MB以下的輕量設(shè)備,對(duì)應(yīng)JS引擎的可用內(nèi)存范圍為48-64KB。本文也將以此類(lèi)設(shè)備為例進(jìn)行分析。
當(dāng)整個(gè)頁(yè)面渲染比較復(fù)雜時(shí),JS運(yùn)行內(nèi)存峰值就可能會(huì)超過(guò)JS引擎分配到的最大可用內(nèi)存,導(dǎo)致頁(yè)面無(wú)法渲染。
List組件是JS UI框架下最基本的容器組件之一,提供了一系列相同寬度的列表項(xiàng)。在應(yīng)用開(kāi)發(fā)過(guò)程中,經(jīng)常會(huì)使用List容器組件來(lái)呈現(xiàn)大量的數(shù)據(jù)。所以,在List組件應(yīng)用的開(kāi)發(fā)過(guò)程中,開(kāi)發(fā)者應(yīng)充分考慮內(nèi)存優(yōu)化問(wèn)題。
本期,我們將通過(guò)List組件開(kāi)發(fā)一個(gè)通訊錄頁(yè)面,并采用list+for的方案對(duì)整個(gè)頁(yè)面進(jìn)行優(yōu)化,達(dá)到減小JS運(yùn)行內(nèi)存的目的。
一、代碼實(shí)現(xiàn)
如下所示,是一張簡(jiǎn)單的通訊錄頁(yè)面,包含了姓名、電話及對(duì)應(yīng)圖片。下面將通過(guò)兩種實(shí)現(xiàn)方式來(lái)對(duì)比代碼性能。
方法一:直接書(shū)寫(xiě)對(duì)應(yīng)的組件頁(yè)面
使用HML直接撰寫(xiě)整個(gè)組件頁(yè)面的內(nèi)容,代碼如下:
《div class=“container”》 《list class=“l(fā)ist”》 《list-item class=“l(fā)ist-item”》 《image class=“image” src=“/common/1.png”》《/image》 《div class=“info”》 《text class=“text”》張三《/text》 《marquee class=“detail”》電話:+86 130XXXXXXXX《/marquee》 《/div》 《/list-item》 《list-item class=“l(fā)ist-item”》
《image class=“image” src=“/common/1.png”》《/image》 《div class=“info”》 《text class=“text”》李四《/text》 《marquee class=“detail”》電話:027-6128XXXX《/marquee》
《/div》 《/list-item》 《list-item class=“l(fā)ist-item”》 《image class=“image” src=“/common/1.png”》《/image》
《div class=“info”》 《text class=“text”》王五《/text》 《marquee class=“detail”》電話:+86 150xxxxxx《/marquee》 《/div》 《/list-item》 《list-item class=“l(fā)ist-item”》 《image class=“image” src=“/common/1.png”》《/image》 《div class=“info”》
《text class=“text”》小明《/text》 《marquee class=“detail”》電話:+86 130XXXXXXXX《/marquee》
《/div》 《/list-item》 《list-item class=“l(fā)ist-item”》 《image class=“image” src=“/common/2.png”》《/image》 《div class=“info”》 《text class=“text”》小紅《/text》
《marquee class=“detail”》電話:+86 180XXXX 《/marquee》 《/div》 《/list-item》 。。. 《/list》 《input value=“非for” on:click=“changeNextPage” class=“button”》《/input》《/div》
方法二:通過(guò)for指令來(lái)書(shū)寫(xiě)對(duì)應(yīng)的組件頁(yè)面
針對(duì)方法一中的實(shí)現(xiàn),采用for指令來(lái)改進(jìn),使對(duì)應(yīng)頁(yè)面更簡(jiǎn)潔,對(duì)應(yīng)修改后代碼如下:
《div class=“container”》 《list class=“l(fā)ist” on:scrollend=“changeNextPage”》 《list-item class=“l(fā)ist-item” for = “{{listData}}”》 《image class = “image” src = “/common/{{$item.src}}”》《/image》 《div class = “info”》 《text class=“text”》{{$item.name}}《/text》
《marquee class = “detail”》電話: {{$item.phone}}《/marquee》 《/div》 《/list-item》 《/list》《/div》
對(duì)應(yīng)的for指令的渲染數(shù)組代碼如下:
export default { data: { listData:[] }, onInit() { for (var i = 0; i 《 10; i++) { this.listData.push({‘name’:‘張三’, src :‘1.png’, phone:“+86 130XXXXXX”}); this.listData.push({‘name’:‘李四’, src :‘2.png’, phone:“027-6128XXXX”});
this.listData.push({‘name’:‘王五’, src :‘1.png’, phone:“+ 86 150XXXXXX”}); this.listData.push({‘name’:‘小明’, src :‘1.png’, phone:‘+86 130XXXXXX’}); this.listData.push({‘name’:‘小紅’, src :‘2.png’, phone:‘+86 180XXXX’}); } }}
二、性能測(cè)試
這里,我們針對(duì)不同的item數(shù)量,分別測(cè)試了以上兩種實(shí)現(xiàn)方式的JS運(yùn)行性能,JS運(yùn)行內(nèi)存與JS運(yùn)行內(nèi)存峰值如下圖所示:
圖2 兩種方法的內(nèi)存占用
由上表測(cè)試數(shù)據(jù)可以看出,采用方法二進(jìn)行渲染,JS運(yùn)行內(nèi)存會(huì)出現(xiàn)比較大的浮動(dòng)。但是使用方法一,對(duì)應(yīng)的JS運(yùn)行內(nèi)存基本保持不變,這種差異是由兩種不同的頁(yè)面加載渲染機(jī)制造成的。
方法一的加載機(jī)制:對(duì)整個(gè)頁(yè)面一次性全部進(jìn)行加載,在加載完成后,會(huì)對(duì)List組件頁(yè)面占用的JS運(yùn)行內(nèi)存進(jìn)行釋放。頁(yè)面后續(xù)滑動(dòng),并不會(huì)觸發(fā)組件的解析,從而不會(huì)影響JS運(yùn)行時(shí)內(nèi)存數(shù)據(jù)。
方法二的加載機(jī)制:每次滑動(dòng)屏幕會(huì)加載當(dāng)前顯示頁(yè)面以及緩存部分的item,超出屏幕之外的item會(huì)對(duì)其占用的JS內(nèi)存資源進(jìn)行回收。當(dāng)List組件頁(yè)面下滑到新的item時(shí)會(huì)重新創(chuàng)建請(qǐng)求,這種情況下會(huì)降低一部分的滑動(dòng)性能,但是可以實(shí)現(xiàn)按需加載,降低JS運(yùn)行內(nèi)存峰值。
三、優(yōu)缺點(diǎn)對(duì)比
方法一的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):首次頁(yè)面顯示成功后,JS運(yùn)行內(nèi)存比較穩(wěn)定,不會(huì)出現(xiàn)后續(xù)滑動(dòng)崩潰的問(wèn)題,且穩(wěn)定顯示后占用的JS運(yùn)行內(nèi)存較小。
缺點(diǎn):由于頁(yè)面會(huì)一次性全部進(jìn)行解析,在解析比較復(fù)雜的頁(yè)面時(shí),會(huì)對(duì)JS運(yùn)行內(nèi)存峰值造成比較大的壓力,甚至?xí)?dǎo)致對(duì)應(yīng)的頁(yè)面無(wú)法啟動(dòng)。
方法二的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
1. 在頁(yè)面啟動(dòng)時(shí),只對(duì)顯示部分進(jìn)行加載,因此可以降低頁(yè)面啟動(dòng)時(shí)JS運(yùn)行內(nèi)存。
2. 由于整個(gè)頁(yè)面始終只保持對(duì)顯示界面的元素進(jìn)行渲染。因此,針對(duì)稍復(fù)雜的界面,相較于方法一JS運(yùn)行內(nèi)存峰值更小。
缺點(diǎn):
1. List組件的內(nèi)容,需要通過(guò)$item進(jìn)行訪問(wèn), item顯示時(shí)會(huì)創(chuàng)建對(duì)應(yīng)的數(shù)據(jù)監(jiān)聽(tīng)對(duì)象來(lái)檢測(cè)數(shù)據(jù)的變化,比如上述界面中,一個(gè)item會(huì)創(chuàng)建3個(gè)數(shù)據(jù)監(jiān)聽(tīng),list中進(jìn)行繪制的item的數(shù)量為5,因此會(huì)創(chuàng)建15個(gè)數(shù)據(jù)監(jiān)聽(tīng),從而增加 15 * 200B(單個(gè)字節(jié)) = 3000B的數(shù)據(jù)監(jiān)聽(tīng)開(kāi)銷(xiāo)。
2. 隨著list組件向下滑動(dòng),會(huì)增加數(shù)組監(jiān)聽(tīng)占用的內(nèi)存,從而增加對(duì)應(yīng)的JS運(yùn)行內(nèi)存。因此使用方法二,JS運(yùn)行內(nèi)存會(huì)一直上漲,直到最后一個(gè)item渲染。
四、使用建議
針對(duì)上述表現(xiàn),我們總結(jié)了如下使用場(chǎng)景供開(kāi)發(fā)者參考:
圖3 使用建議
總而言之,采用方法二開(kāi)發(fā)List組件可以降低JS運(yùn)行內(nèi)存峰值,但是會(huì)增加JS運(yùn)行時(shí)內(nèi)存。當(dāng)頁(yè)面比較簡(jiǎn)單,item數(shù)量低于20個(gè),建議采用方法一。當(dāng)頁(yè)面item超過(guò)20個(gè),或者頁(yè)面占用JS內(nèi)存峰值比較大,建議采用方法二。
責(zé)任編輯:haq
-
編程
+關(guān)注
關(guān)注
88文章
3634瀏覽量
93855 -
JS
+關(guān)注
關(guān)注
0文章
78瀏覽量
18135 -
代碼
+關(guān)注
關(guān)注
30文章
4809瀏覽量
68816
原文標(biāo)題:JS UI框架下,List組件運(yùn)行時(shí)的內(nèi)存優(yōu)化
文章出處:【微信號(hào):HarmonyOS_Dev,微信公眾號(hào):HarmonyOS開(kāi)發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論