查看更多学习笔记:GitHub:LoveEmiliaForever
微信小程序开发指南
微信小程序开发文档
启动
在小程序启动时,微信会为小程序展示一个固定的启动界面,界面内包含小程序的图标、名称和加载提示图标
此时,微信会在背后完成几项工作:下载小程序代码包、加载小程序代码包、初始化小程序首页

代码包下载
小程序第一次启动时,微信需要下载小程序代码包,如果小程序代码包未更新且还被保留在缓存中,则下载小程序代码包的步骤会被跳过
小程序代码包不是小程序的源代码,而是编译、压缩、打包之后的代码包
对低于1MB的代码包,其下载时间可以控制在929ms(iOS)、1500ms(Android)内
- 精简代码,去掉不必要的WXML结构和未使用的WXSS定义
- 减少在代码包中直接嵌入的资源文件
- 压缩图片,使用适当的图片格式
分包加载流程
如果小程序比较复杂,优化后的代码总量可能仍然比较大,此时可以采用分包加载的方式进行优化
采用分包时,小程序的代码包可以被划分为几个:
- 一个是
主包,包含小程序启动时会马上打开的页面代码和相关资源 - 其余是
分包,包含其余的代码和资源
小程序启动时,只需要先将主包下载完成,就可以立刻启动小程序,显著降低小程序代码包的下载时间
分包的目录结构

分包的app.json配置
{
"pages":[
"pages/index",
"pages/logs"
],
"subPackages": [
{
"root": "packageA",
"pages": [
"pages/cat",
"pages/dog"
]
}, {
"root": "packageB",
"pages": [
"pages/apple",
"pages/banana"
]
}
]
}
组织成上图的形式,这两个子目录就构成了两个分包,每个分包下都可以有自己的页面代码和资源文件
除掉这两个目录的部分就是小程序的主包,启动时需要访问的页面及其依赖的资源文件应放在主包中
代码包加载
微信会在小程序启动前为小程序准备好通用的运行环境
这个运行环境包括几个供小程序使用的线程,并在其中完成小程序基础库的初始化,预先执行通用逻辑,尽可能做好小程序的启动准备
小程序的代码包被下载(或从缓存中读取)完成后,小程序的代码会被加载到适当的线程中执行
所有app.js、页面所在的JS文件和所有其他被require的JS文件会被自动执行一次,小程序基础库会完成所有页面的注册
需要注意的是,如果一个页面被多次创建,并不会使得这个页面所在的JS文件被执行多次,而仅仅是根据初始数据多生成了一个页面实例(this),在页面JS文件中直接定义的变量,在所有这个页面的实例间是共享的
在小程序代码包加载完毕后,小程序基础库会根据启动路径选择一个页面来启动
这时会根据页面路径和初始数据创建一个新页面,页面创建和运行期间会涉及许多数据通信和页面渲染
页面层级的准备
在视图层内,小程序的每一个页面都独立运行在一个页面层级上
小程序启动时仅有一个页面层级,每次调用wx.navigateTo,都会创建一个新的页面层级,相对地,wx.navigateBack会销毁一个页面层级
对于每一个新的页面层级,视图层都需要进行一些额外的准备工作
页面层级的准备工作分为三个阶段
- 启动一个WebView
- 在WebView中初始化基础库,还会进行一些基础库内部优化
- 注入小程序WXML结构和WXSS样式(这一阶段无法在小程序启动前执行)

对于wx.redirectTo,这个调用不会打开一个新的页面层级,而是将当前页面层级重新初始化
数据通信
在每个小程序页面的生命周期中,存在着若干次页面数据通信
逻辑层向视图层发送页面数据(data和setData的内容),视图层向逻辑层反馈用户事件
页面初始数据通信
在小程序启动或一个新的页面被打开时,页面的初始数据(data)和路径等相关信息会从逻辑层发送给视图层,用于视图层的初始渲染
Native层会将这些数据直接传递给视图层,同时向用户展示一个新的页面层级,视图层在这个页面层级上进行界面绘制
视图层接收到相关数据后,根据页面路径来选择合适的WXML结构,WXML结构与初始数据相结合,得到页面的第一次渲染结果

页面初始化时间大致由页面初始数据通信时间和初始渲染时间两部分构成
数据通信的时间指数据从逻辑层开始组织数据到视图层完全接收完毕的时间,数据量小于64KB时总时长可以控制在30ms内
更新数据通信
初始渲染完毕后,视图层可以在开发者调用setData后执行界面更新
数据传输时,逻辑层会执行一次JSON.stringify来去除掉setData数据中不可传输的部分
逻辑层还会将setData所设置的数据字段与data合并,使开发者可以用this.data读取到变更后的数据
- 不要过于频繁调用setData,应考虑将多次setData合并成一次setData调用
- 数据通信的性能与数据量正相关,因而如果有一些数据字段
不在界面中展示且数据结构比较复杂或包含长字符串,则不应使用setData来设置这些数据 - 与界面渲染无关的数据最好不要设置在data中,可以考虑设置在page对象的其他字段下
用户事件通信
视图层会接受用户事件,如点击事件、触摸事件等
- 当一个用户事件被触发且有相关的事件监听器需要被触发时,视图层会将信息反馈给逻辑层
- 如果一个事件没有绑定事件回调函数,则这个事件不会被反馈给逻辑层
- 视图层中有一套高效的事件处理体系,可以快速完成事件生成、冒泡、捕获等过程
视图层将事件反馈给逻辑层时,同样需要一个通信过程,通信的方向是从视图层到逻辑层
- 去掉不必要的事件绑定(WXML中的bind和catch),从而减少通信的数据量和次数
- 事件绑定时需要传输target和currentTarget的dataset,因而不要在节点的data前缀属性中放置过大的数据
视图层渲染
视图层在接收到初始数据(data)和更新数据(setData数据)时,需要进行视图层渲染
初始渲染
初始渲染发生在页面刚刚创建时

在这整个流程中,时间开销大体上与节点树中节点的总量成正比例关系
因而减少WXML中节点的数量可以有效降低初始渲染和重渲染的时间开销,提升渲染性能
重渲染
初始渲染完毕后,视图层可以多次应用setData的数据,每次应用setData数据时,都会执行重渲染来更新界面
- 初始渲染中得到的data和当前节点树会保留下来用于重渲染
- 每次重渲染时,将data和setData数据套用在WXML片段上,得到一个新节点树
- 将新节点树与当前节点树进行比较,这样可以得到哪些节点的哪些属性需要更新、哪些节点需要添加或移除
- 最后,将setData数据合并到data中,并用新节点树替换旧节点树

去掉不必要设置的数据、减少setData的数据量也有助于提升这一个步骤的性能
原生组件通信
一些原生组件支持使用context来更新组件
不同于setData,使用context来更新组件并不会涉及到重渲染过程,数据通信过程也不同
使用context时,数据从逻辑层传到native层后,直接传入组件中,这样可以显著降低传输延迟

882

被折叠的 条评论
为什么被折叠?



