欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

小程序性能優(yōu)化實(shí)踐總結(jié) - 新聞資訊 - 云南小程序開(kāi)發(fā)|云南軟件開(kāi)發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開(kāi)發(fā)/軟件開(kāi)發(fā)

知識(shí)

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X(jué)表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營(yíng)銷(xiāo)的便利,運(yùn)營(yíng)的高效,讓網(wǎng)站成為營(yíng)銷(xiāo)工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!

您當(dāng)前位置>首頁(yè) » 新聞資訊 » 小程序相關(guān) >

小程序性能優(yōu)化實(shí)踐總結(jié)

發(fā)表時(shí)間:2021-1-5

發(fā)布人:葵宇科技

瀏覽次數(shù):45

項(xiàng)目簡(jiǎn)述 & 問(wèn)題

先簡(jiǎn)單介紹一下項(xiàng)目,就是一個(gè)比較常規(guī)的點(diǎn)餐小程序。

界面如圖:

左邊是分類(lèi)菜單,右邊是長(zhǎng)列表,有多個(gè)分類(lèi)的商品,單個(gè)分類(lèi)滾動(dòng)完后可以繼續(xù)滾動(dòng)切換到下一個(gè)分類(lèi),同時(shí)左邊的分類(lèi)菜單選中態(tài)會(huì)跟著切換到當(dāng)前商品列表顯示的分類(lèi)。

考慮到更好的用戶(hù)體驗(yàn),以及參考了美團(tuán)等點(diǎn)餐小程序,這個(gè)商品列表的數(shù)據(jù)是一次性返回的。目前遇到的問(wèn)題就是,當(dāng)商品數(shù)量比較多時(shí),首次渲染時(shí)間很長(zhǎng),而且頁(yè)面會(huì)卡頓。

優(yōu)化方向

邏輯優(yōu)化

小聲bb:其實(shí)就是原來(lái)代碼(由于歷史原因)寫(xiě)得太爛了……OTL

先放個(gè)圖

小聲bb:連小程序都看不下去了,要警告了o(╯□╰)o

微信開(kāi)發(fā)者工具都有警告了,而且提示里面也有定位到具體代碼的位置,所以關(guān)鍵就是這個(gè) setData ?。?!

我們可以先看看官方對(duì)于小程序性能以及 setData 優(yōu)化的一些建議。

具體實(shí)踐:

1. setData 不能一次性傳太多數(shù)據(jù),如果列表太長(zhǎng),可以分開(kāi)渲染【比如轉(zhuǎn)化為二維數(shù)組,每次循環(huán)渲染一個(gè)數(shù)組】。

v1:簡(jiǎn)單粗暴版

// 每次渲染一個(gè)分類(lèi)
// 假設(shè)goodsList是一個(gè)二維數(shù)組
goodsList.forEach((item, index) => {
    this.setData({
        [`goodsList[${index}]`]: item
    })
})
復(fù)制代碼

像上面這樣寫(xiě)會(huì)有一個(gè)問(wèn)題,頁(yè)面首屏渲染是快了,但是點(diǎn)擊頁(yè)面操作(比如加購(gòu)按鈕等),頁(yè)面會(huì)卡住,等一下才有反應(yīng),操作反饋延遲嚴(yán)重。

其實(shí)這是因?yàn)?,這個(gè)循環(huán)是把單次 setData 數(shù)量減少了,但是卻變成了循環(huán)多次 setData,我們看著首屏顯示好了,但是其實(shí)其他分類(lèi)(其他數(shù)組)還在渲染,線(xiàn)程還是忙碌狀態(tài),JS 線(xiàn)程一直在編譯執(zhí)行渲染,點(diǎn)擊事件不能及時(shí)傳遞到邏輯層,邏輯層亦無(wú)法及時(shí)將操作處理結(jié)果及時(shí)傳遞到視圖層。

v2:定時(shí)器hack版

既然js線(xiàn)程忙著渲染,那我們可以強(qiáng)制讓它先停下來(lái)。于是有了v2的定時(shí)器hack版。

// 每次渲染一個(gè)分類(lèi)
let len = data.goodsList ? data.goodsList.length : 0;
let idx = 0
let timer = setInterval(() => {
    if (idx < len) {
        that.setData({
            [`goodsList[${idx}]`]: data.goodsList[idx]
        });
        idx++
    } else {
        clearInterval(timer)
    }
}, 15);
復(fù)制代碼

現(xiàn)在首屏渲染速度問(wèn)題解決了,點(diǎn)擊按鈕延遲響應(yīng)問(wèn)題也解決了。就是代碼有點(diǎn)hack,逼死強(qiáng)迫癥o(╯□╰)o

v3:大殺器——虛擬列表

虛擬列表簡(jiǎn)單說(shuō)原理就是只渲染當(dāng)前顯示屏幕區(qū)域以及前n屏和后n屏的數(shù)據(jù),用一個(gè)單獨(dú)的字段保存當(dāng)前需要顯示的數(shù)組(就是當(dāng)前一屏+前n屏+后n屏),每次列表滾動(dòng)的時(shí)候重新計(jì)算需要顯示的數(shù)據(jù),更新這個(gè)字段,頁(yè)面就會(huì)相應(yīng)更新了。這樣就能保證頁(yè)面上的元素節(jié)點(diǎn)數(shù)量不會(huì)太多,就可以支持大量數(shù)據(jù)的長(zhǎng)列表需求。

更詳細(xì)的原理和實(shí)現(xiàn)各位同學(xué)們可以自己搜一下,此處不展開(kāi)。

2. setData 可以支持顆粒更新,指定到具體的屬性。

比如加購(gòu)等操作,需要更新商品右上角的小數(shù)字,可以這樣寫(xiě):

this.setData({
    [`goodsList[${categoryIndex}][${goodsIndex}].num`]: goodsItem.num
})
復(fù)制代碼

3. 跟頁(yè)面無(wú)關(guān)的數(shù)據(jù)不要保存在 data,不要用 setData 更新,因?yàn)?setData 會(huì)觸發(fā)頁(yè)面渲染。

eg:

Page({
    data: {
        ...
    },
    // 跟頁(yè)面渲染無(wú)關(guān)的數(shù)據(jù)
    state: {
        hasLogin: false,
    },
    ...
})

// 更新的時(shí)候直接賦值就行
this.state.hasLogin = true
復(fù)制代碼

PS:或者甚至不需要掛載到 page 對(duì)象下,直接用普通變量保存。

4. 圖片大小優(yōu)化

在長(zhǎng)列表中圖片大小如果不加限制,大量的大圖會(huì)占用很多內(nèi)存,有可能導(dǎo)致iOS客戶(hù)端內(nèi)存占用上升,從而觸發(fā)系統(tǒng)回收小程序頁(yè)面。除了內(nèi)存問(wèn)題外,大圖片也會(huì)造成頁(yè)面切換的卡頓。

解決辦法就是根據(jù)當(dāng)前顯示的圖片區(qū)域大小,取尺寸剛好合適(2倍-3倍圖)的圖片。

建議圖片用CDN,一般CDN服務(wù)廠商提供圖片服務(wù)的都會(huì)提供裁剪圖片的接口,然后接口只返回原圖鏈接,前端根據(jù)需要傳參數(shù)裁剪圖片。前端具體做法可以寫(xiě)公共的圖片處理方法,或者自己封裝圖片組件。

5. 減少不必要的數(shù)據(jù)請(qǐng)求

比如在該點(diǎn)餐頁(yè)面進(jìn)入時(shí)需要獲取定位,然后根據(jù)定位獲取最近的門(mén)店,前面兩個(gè)接口都需要請(qǐng)求(具體可以根據(jù)業(yè)務(wù)需求),而最后如果獲取到的距離最近的門(mén)店跟上次一樣,則不需要重新獲取店鋪詳情和商品數(shù)據(jù)。

體驗(yàn)優(yōu)化

1. 合并短時(shí)間內(nèi)的多個(gè)loading提示

還是該點(diǎn)餐頁(yè)面流程,像上文說(shuō)過(guò)的,進(jìn)入頁(yè)面時(shí)需要獲取定位接口,等定位接口返回結(jié)果了再拿定位取值去獲取距離最近的店鋪,最后才是請(qǐng)求店鋪和商品數(shù)據(jù)。

這三個(gè)接口是串行的。此時(shí)如果我們每個(gè)接口都彈出一個(gè)loading提示,就會(huì)出現(xiàn)loading顯示一會(huì)兒,消失,又顯示一會(huì)兒,又消失……這樣的現(xiàn)象,這樣的體驗(yàn)是不太好的。

建議可以通過(guò)封裝請(qǐng)求,并且在請(qǐng)求里統(tǒng)一處理loading,來(lái)合并短時(shí)間內(nèi)多次發(fā)起請(qǐng)求的多個(gè)loading。

eg:

let showLoadingTimer = null;
let showRequestLoading = false; // 標(biāo)記是否正在顯示loading

/**
 * 封裝request
 * @param {*} {showLoading:是否需要顯示loading, options:request參數(shù),如url,data等} 
 */
function request({showLoading = true, ...options}) {
    // 顯示request loading
    handleShowLoading(showLoading)

    wx.request({
        ...
        complete() {
            // 關(guān)閉request loading
            handleShowLoading(false)
        }
    })
}

/**
 * 封裝request loading
 * 短時(shí)間內(nèi)如果調(diào)用多次showLoading,會(huì)合并在一起顯示,而不是每個(gè)都閃現(xiàn)一下
 * @param showLoading
 */
function handleShowLoading(showLoading) {
    if (showLoading) {
        // 顯示loading
        clearTimeout(showLoadingTimer);
        if (!showRequestLoading) {
            showRequestLoading = true;
            wx.showNavigationBarLoading();
            wx.showLoading({ title: "加載中", mask: true })
        }
    } else {
        // 200ms后關(guān)閉loading
        showLoadingTimer = setTimeout(() => {
            showRequestLoading = false;
            wx.hideNavigationBarLoading();
            wx.hideLoading()
        }, 200)
    }
}
復(fù)制代碼

2. 整個(gè)頁(yè)面初次加載時(shí)可以使用頁(yè)面loading動(dòng)畫(huà)或骨架屏,優(yōu)化加載中體驗(yàn)。

3. 靜默獲取、更新數(shù)據(jù)

比如這個(gè)點(diǎn)餐頁(yè)每次 onShow 都會(huì)調(diào)用定位接口和獲取最近門(mén)店接口,但是不顯示loading,用戶(hù)就沒(méi)有感知,體驗(yàn)比較好。

接口優(yōu)化

需要關(guān)注接口的粒度控制。 因?yàn)橛袝r(shí)候合并接口,前端可以減少一次請(qǐng)求,體驗(yàn)更好;但有時(shí)候如果接口的數(shù)據(jù)太多,響應(yīng)太慢,就可以考慮是否某部分?jǐn)?shù)據(jù)可以后置獲取,讓主要的頁(yè)面內(nèi)容先渲染出來(lái),根據(jù)這個(gè)設(shè)計(jì)來(lái)拆分接口。

比如項(xiàng)目中的點(diǎn)餐頁(yè)面,原來(lái)購(gòu)物車(chē)數(shù)據(jù)和商品規(guī)格彈窗顯示的詳情數(shù)據(jù)都是在獲取店鋪商品接口一次性返回的,而這個(gè)接口本來(lái)由于設(shè)計(jì)需要一次返回所有商品,就會(huì)造成數(shù)據(jù)量太大,而且后端需要查詢(xún)的表也更多。于是把獲取購(gòu)物車(chē),和商品詳情接口都拆分為單獨(dú)的接口,獲取店鋪商品接口的響應(yīng)時(shí)間就減少了,頁(yè)面也能更快顯示出來(lái)。

總結(jié)

其實(shí)上面提到的邏輯優(yōu)化和接口優(yōu)化很多都是細(xì)節(jié),并不是太高深的技術(shù),我們平時(shí)迭代的時(shí)候就可以注意。而體驗(yàn)方面的優(yōu)化則需要前端同學(xué)在前端技術(shù)以外更多關(guān)注用戶(hù)體驗(yàn)和設(shè)計(jì)方面的知識(shí)啦,而且這也是一個(gè)有追求的前端應(yīng)該具備的技能……←_←



相關(guān)案例查看更多