小程序模板網(wǎng)

你可能不知道的小程序(上篇)

發(fā)布時(shí)間:2018-11-27 15:28 所屬欄目:小程序開(kāi)發(fā)教程

為了讓大家更好的理解小程序的一些限制和做一些優(yōu)化,下面從小程序的基礎(chǔ)架構(gòu)講起,如有不對(duì)的地方,望指正,請(qǐng)輕噴 :smile:

一. 頁(yè)面棧限制最多10層

首先,我們看看下圖,小程序的架構(gòu)如下:

我們可以看到,一個(gè)頁(yè)面使用一個(gè) WebView 線程進(jìn)行渲染。 如果于頁(yè)面棧有 10 層,則會(huì)開(kāi)啟 10 個(gè) WebView 線程,占多一點(diǎn)內(nèi)存,所以對(duì)頁(yè)面棧進(jìn)行了限制。

那如果在10層頁(yè)面棧的限制內(nèi),由于頁(yè)面的內(nèi)容過(guò)于復(fù)雜,內(nèi)存爆了怎么辦? 小程序內(nèi)部有一個(gè)回收機(jī)制,如果內(nèi)存緊張時(shí),會(huì)回收掉一部分 WebView 。

很多人可能會(huì)覺(jué)得, 10 層頁(yè)面?;疽呀?jīng)夠用了,無(wú)須關(guān)注這方面的限制了。

但是如果出現(xiàn)循環(huán)引用的話,用戶反復(fù)點(diǎn)擊,則很容易出現(xiàn)爆棧的情況。 如下圖:

所以,在開(kāi)發(fā)之前,提前梳理好頁(yè)面之間的跳轉(zhuǎn),合理使用 navigator ,redirectTo, navigateBack …… 是非常重要的。

當(dāng)然,作為一個(gè)程序員,我并不想在跳轉(zhuǎn)的時(shí)候去時(shí)時(shí)刻刻的關(guān)注我有沒(méi)有正確引用,有沒(méi)有超出10層頁(yè)面棧。 完全可以對(duì)小程序的跳轉(zhuǎn)做一個(gè)封裝。

因?yàn)橹挥?wx.navigateTo 才會(huì)使頁(yè)面棧 + 1 ,那我們只要對(duì)這個(gè)方法做一層兜底處理即可。 如下代碼:

const PAGE_LIMIT = 10
const pages = getCurrentPages()
if(pages.length >= PAGE_LIMIT) {
  // 使用 wx.redirectTo 方法
}

這樣就可以隨心所欲的跳來(lái)跳去了。

二. JsCore

小程序的邏輯層是在 JsCore 中運(yùn)行的。限制如下:

  • 沒(méi)有 Window、Document 對(duì)象,也就無(wú)法使用 基于 DOM 的一些庫(kù). 暫無(wú)解決方法。

還是從一張圖說(shuō)起:

不同于頁(yè)面的渲染,所有的腳本邏輯都是跑在同一個(gè) JsCode 線程里面,類似于路由中改變 Hash 值。 因此也會(huì)引起下面一些常見(jiàn)的坑

  1. 需要自己清理頁(yè)面的 setTimeout 或者 setInterval 定時(shí)器
  2. 如果要求頁(yè)面每次出現(xiàn)都是最新的數(shù)據(jù),則要把拉取數(shù)據(jù)的邏輯放在 onShow 中執(zhí)行,別放在 onload 中。
  3. 若追求“極致化體驗(yàn)”,在用戶切到下一個(gè)頁(yè)面的時(shí)候,可以在 onHide 中 abort 掉沒(méi)有請(qǐng)求成功的接口,把即將處理的 setData 去掉,可以減輕最新頁(yè)面的邏輯,讓最新頁(yè)面最快渲染展示。

三. 原生組件層級(jí)最高

像 canvas , video ,input ,map ,picker …… 組件,官方直接使用原生組件,渲染方式如下圖:

從上圖很容易就可以看出,Navtive 組件的層級(jí)是最高的,那么僅僅去改變 z-index 也無(wú)法讓其他組件覆蓋原生組件。還好,官方給出了一個(gè)解決方案:

  • 使用 cover-view cover-image 將希望層級(jí)變高的組件也包裹成“原生組件”

四. 獨(dú)特的網(wǎng)絡(luò)請(qǐng)求,本地存儲(chǔ)

  1. 獨(dú)特的 Storage 存儲(chǔ)
    • 以用戶緯度隔離,同一個(gè)設(shè)備,A 無(wú)法訪問(wèn) B 用戶的數(shù)據(jù)。
    • 持久緩存,只有在用戶關(guān)掉小程序才會(huì)刪除,如果空間不足,會(huì)進(jìn)行 LRU ,也就是不經(jīng)常使用的小程序的數(shù)據(jù)緩存區(qū)域會(huì)被全部清空。
    • 在體驗(yàn)版、開(kāi)發(fā)版、和線上版都共用一套,并不會(huì)隔離。
    • 沒(méi)有 Cookie
  2. Request uploadFile downloadFile 并發(fā)最多10個(gè)請(qǐng)求
  3. 只支持 HTTPS WSS

如果以往在移動(dòng)端, PC 的接口會(huì)使用 Cookie 進(jìn)行一些處理,那在小程序中使用該接口就比較尷尬了。

因此,我們可以在小程序中也模擬出 Cookie ,如下圖:

在 Storage 中隔離一個(gè)字段,用來(lái)做 Cookie ,下面用了一個(gè)小技巧,把 Cookie 的內(nèi)容存放于內(nèi)存中,而非每次都從 storage 中讀取。

let cookie = (function(){
    return wx.getStorageSync('cookies');
}())
const Cooke = {
  getCookie(){}, //從內(nèi)存中獲取cookie
  setCookie(){}, // 設(shè)置cookie
  setCookieInHeader(){}, //根據(jù)response的Header設(shè)置cookie
  removeCookie() {},  //刪除cookie
  isExpired() {} //判斷是否過(guò)期
}

然后,我們?cè)诿看?Request 成功后,解析 Header 中 SET-COOKIE 屬性設(shè)置 Cookie ,在每一次請(qǐng)求的時(shí)候,手動(dòng)在 Header 中設(shè)置 Cookie 。這樣就完美地模擬瀏覽器的 Cookie 概念了。

  1. 并發(fā)請(qǐng)求處理

設(shè)置一個(gè)隊(duì)列,如果請(qǐng)求處理完畢,則移出隊(duì)列,如果當(dāng)前數(shù)組超過(guò)10個(gè)請(qǐng)求,則進(jìn)入等待狀態(tài)。大概代碼如下:

class Request {
    constructor() {
        this.maxLimit = 10;
        this.requestQueue = []; // 請(qǐng)求隊(duì)列
        this.requestIng = 0; //當(dāng)前并發(fā)數(shù)
    }
    request () {
        // 判斷是否超出并發(fā)數(shù)
        if(this.requestIng >= this.maxLimit) {
            // 推入請(qǐng)求隊(duì)列
        }else {
            this.requestIng ++;
            // 執(zhí)行成功后 - 1 ,從 requestQueue 中取出重新請(qǐng)求
        }
    }
}

五. setData

好吧,還是從一張圖說(shuō)起,顯然,我們可以看出,每一次 setData 都是一次線程通信。

線程通信成本很高,非常耗時(shí)間,因此官方明確的給出了建議:

  1. 將多次 setData 合并成一次進(jìn)行調(diào)用
  2. 只 setData 對(duì)象改變的某個(gè)值
data: {
    array: {
        changeData: '我改變了',
        noChangeData: '我沒(méi)有改變'
    },
},
this.setData({
    'array.changeData':'changed data'
})
  1. 與界面渲染無(wú)關(guān)的字段不要放在 data 中
data: {
    view: '與界面相關(guān)的數(shù)據(jù)'
},
noRelaView: '與界面無(wú)關(guān)'
復(fù)制代碼


易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開(kāi)源 碼云倉(cāng)庫(kù):starfork
本文地址:http://www.u-renovate.com/wxmini/doc/course/24975.html 復(fù)制鏈接 如需定制請(qǐng)聯(lián)系易優(yōu)客服咨詢:800182392 點(diǎn)擊咨詢
QQ在線咨詢
AI智能客服 ×