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

栏目: IOS · Android · 发布时间: 6年前

内容简介:为了让大家更好的理解小程序的一些限制和做一些优化,下面从小程序的基础架构讲起,如有不对的地方,望指正,请轻喷 :smile:首先,我们看看下图,小程序的架构如下:我们可以看到,一个页面使用一个 WebView 线程进行渲染。 如果于页面栈有 10 层,则会开启 10 个 WebView 线程,占多一点内存,所以对页面栈进行了限制。

为了让大家更好的理解小程序的一些限制和做一些优化,下面从小程序的基础架构讲起,如有不对的地方,望指正,请轻喷 :smile:

一. 页面栈限制最多10层

首先,我们看看下图,小程序的架构如下:

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

我们可以看到,一个页面使用一个 WebView 线程进行渲染。 如果于页面栈有 10 层,则会开启 10 个 WebView 线程,占多一点内存,所以对页面栈进行了限制。

那如果在10层页面栈的限制内,由于页面的内容过于复杂,内存爆了怎么办? 小程序内部有一个回收机制,如果内存紧张时,会回收掉一部分 WebView 。

很多人可能会觉得, 10 层页面栈基本已经够用了,无须关注这方面的限制了。

但是如果出现循环引用的话,用户反复点击,则很容易出现爆栈的情况。 如下图:

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

所以,在开发之前,提前梳理好页面之间的跳转,合理使用 navigator ,redirectTo, navigateBack …… 是非常重要的。

当然,作为一个程序员,我并不想在跳转的时候去时时刻刻的关注我有没有正确引用,有没有超出10层页面栈。 完全可以对小程序的跳转做一个封装。

因为只有 wx.navigateTo 才会使页面栈 + 1 ,那我们只要对这个方法做一层兜底处理即可。 如下代码:

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

这样就可以随心所欲的跳来跳去了。

二. JsCore

小程序的逻辑层是在 JsCore 中运行的。限制如下:

  • 没有 Window、Document 对象,也就无法使用 基于 DOM 的一些库. 暂无解决方法。

还是从一张图说起:

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

不同于页面的渲染,所有的脚本逻辑都是跑在同一个 JsCode 线程里面,类似于路由中改变 Hash 值。 因此也会引起下面一些常见的坑

  1. 需要自己清理页面的 setTimeout 或者 setInterval 定时器
  2. 如果要求页面每次出现都是最新的数据,则要把拉取数据的逻辑放在 onShow 中执行,别放在 onload 中。
  3. 若追求“极致化体验”,在用户切到下一个页面的时候,可以在 onHide 中 abort 掉没有请求成功的接口,把即将处理的 setData 去掉,可以减轻最新页面的逻辑,让最新页面最快渲染展示。

三. 原生组件层级最高

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

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

从上图很容易就可以看出,Navtive 组件的层级是最高的,那么仅仅去改变 z-index 也无法让其他组件覆盖原生组件。还好,官方给出了一个解决方案:

  • 使用 cover-view cover-image 将希望层级变高的组件也包裹成“原生组件”

四. 独特的网络请求,本地存储

  1. 独特的 Storage 存储
    • 以用户纬度隔离,同一个设备,A 无法访问 B 用户的数据。
    • 持久缓存,只有在用户关掉小程序才会删除,如果空间不足,会进行 LRU ,也就是不经常使用的小程序的数据缓存区域会被全部清空。
    • 在体验版、开发版、和线上版都共用一套,并不会隔离。
    • 没有 Cookie
  2. Request uploadFile downloadFile 并发最多10个请求
  3. 只支持 HTTPS WSS

如果以往在移动端, PC 的接口会使用 Cookie 进行一些处理,那在小程序中使用该接口就比较尴尬了。

因此,我们可以在小程序中也模拟出 Cookie ,如下图:

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

在 Storage 中隔离一个字段,用来做 Cookie ,下面用了一个小技巧,把 Cookie 的内容存放于内存中,而非每次都从 storage 中读取。

let cookie = (function(){
    return wx.getStorageSync('cookies');
}())
const Cooke = {
  getCookie(){}, //从内存中获取cookie
  setCookie(){}, // 设置cookie
  setCookieInHeader(){}, //根据response的Header设置cookie
  removeCookie() {},  //删除cookie
  isExpired() {} //判断是否过期
}
复制代码

然后,我们在每次 Request 成功后,解析 Header 中 SET-COOKIE 属性设置 Cookie ,在每一次请求的时候,手动在 Header 中设置 Cookie 。这样就完美地模拟浏览器的 Cookie 概念了。

  1. 并发请求处理

设置一个队列,如果请求处理完毕,则移出队列,如果当前数组超过10个请求,则进入等待状态。大概代码如下:

class Request {
    constructor() {
        this.maxLimit = 10;
        this.requestQueue = []; // 请求队列
        this.requestIng = 0; //当前并发数
    }
    request () {
        // 判断是否超出并发数
        if(this.requestIng >= this.maxLimit) {
            // 推入请求队列
        }else {
            this.requestIng ++;
            // 执行成功后 - 1 ,从 requestQueue 中取出重新请求
        }
    }
}
复制代码

五. setData

好吧,还是从一张图说起,显然,我们可以看出,每一次 setData 都是一次线程通信。

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

线程通信成本很高,非常耗时间,因此官方明确的给出了建议:

  1. 将多次 setData 合并成一次进行调用
  2. 只 setData 对象改变的某个值
data: {
    array: {
        changeData: '我改变了',
        noChangeData: '我没有改变'
    },
},
this.setData({
    'array.changeData':'changed data'
})
复制代码
  1. 与界面渲染无关的字段不要放在 data 中
data: {
    view: '与界面相关的数据'
},
noRelaView: '与界面无关'
复制代码
@Author:beidan

以上所述就是小编给大家介绍的《你可能不知道的小程序(上篇)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

人件

人件

Tom DeMarco、Timothy Lister / UML China / 清华大学出版社 / 2003-6 / 35.00元

《人件(第2版)》专门讨论了软件开发和维护的团队管理问题,并向人们的传统认识提出了挑战。作者汤姆·迪马可,蒂姆·李斯特在书中推崇人本管理思想,指出知识型企业的核心是人,而不是技术。《人件(第2版)》于1987年首次出版后,曾在西方引起了轰动,被誉为“对美国软件业影响最大的一本书”。《人件(第2版)》还对大中型组织中的软件开发团队如何运作进行了深入探讨。《人件》已成为软件图书中的经典之作。它和《人月......一起来看看 《人件》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具