本文内容,来源于极客学院的分享,这里只做引用。
2017年, 微信正式推出了小程序, 允许外部开发者在微信内部运行自己的代码, 开展业务。
截至目前,小程序已经成为国内前端的一个重要业务,跟 Web 和手机 App 有着同等的重要性
小程序是—种不需要下载安装即可使用的应用 , 它实现了应用"触手可及" 的梦想 , 用户扫-扫或者搜-下即可打开应用
也体现了 " 用完即走 " 的理念 , 用户不用关心是否安装太多应用的问题 。应用将无处不在 , 随时可用 , 但又无需安装卸载
注意的是, 除了微信小程序, 还有百度小程序 、微信小程序 、支付宝小程序 、抖音小程序 ,都是每个平台自己开发的 ,都是有针对性平台的应用程序
小程序并非凭空冒出来的一个概念,当微信中的 WebView 逐渐成为移动 Web 的一个重要入口时 ,微信就有相关的 JS-SDK 。
JS-SDK 解决了移动网页能力不足的问题 ,通过暴露微信的接口使得 Web 开发者能够拥有更多的能 力 , 然而在更多的能力之外 JS-SDK 的模式并 没有解决使用移动网页遇到的体验不良 的问题。
因此需要设计 — 个比较好的系统 , 使得所有开发者在微信中都能获得比较好的体验:
这些是 JS-SDK 做不到的, 需要设计一个全新的小程序系统。
对于小程序的开发,提供一个简单、高效的应用开发框架和丰富的组件及 API ,帮助开发者开发出具有原生体验的服务
其中相比H5,小程序与其的区别有如下:
小程序可以视为 只能用微信打开和浏览的H5,
小程序和网页的技术模型是一样的,用到的 JavaScript 语言和 CSS 样式也是一样的,只是网页的 HTML 标签被稍微修改成了 WXML 标签
因此可以说,小程序页面本质上就是网页
跟vue 和 react 框架一样,微信小程序框架也存在生命周期, 实质也是 -堆会在特定时期执行的函数
小程序中 , 生命周期主要分成了三部分 :
小程序的生命周期函数是在 app.js 里面调用的 ,通过 App(Object) 函数用来注册-个小程序 ,指定其小程序的生命周期回调
官网地址:https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html#%E5%8F%82%E6%95%B0
页面生命周期函数就是当你每进入/切换到一个新的页面的时候, 就会调用的生命周期函数 同样通过 App(Object) 函数用来注册 — 个页面
组件的生命周期指的是 组件自身的 -些函数, 这些函数在特殊的时间点或遇到 一些特殊的框架事件时被自动触发 ,通过 Component(Object) 进行注册组件
注意的是:
组件实例刚刚被创建好时 , created 生命周期被触发
, 此时 , 组件数据 this. data 就是在component 构造器中定义的数据 data , 此时不能调用 setData
在组件完全初始化完毕 、 进入页面节点树后
, attached 生命周期被触发 。此时 , this. data 已被初始化为组件的当前值 。这个生命周期很有用 , 绝大多数初始化工作可以在这个时机进行
在组件离开页面节点树后 , detached 生命周期被触发
。退出 — 个页面时 , 如果组件还在页面节点树中 , 则 detached 会被触发
还有一些特殊的生命周期, 它们并非与组件有很强的关联 ,但有时组件需要获知, 以便组件内部处理。
这样的生命周期称为 "组件所在页面的生命周期 " ,在 pageLifetimes 定义段中定义 ,如下:
Component({
pageLifetimes: {
show: function() {
// 页面被展示
},
hide: function() {
// 页面被隐藏
},
}
})
微信小程序拥有 web 网页和 Application 共同的特征
我们的页面都不是孤立存在的,而是通过和其他页面进行交互,来共同完成系统的功能
在微信小程序中,每个页面可以看成是一个 pageModel, pageModel 全部以 栈 的形式进行管理
常见的微信小程序页面跳转方式有如下 :
wx.navigateTo() 用于保留当前页面 、跳转到应用内的某个页面 使用 wx.navigateBack 可以返回到原页面。
对于页面不是特别多的小程序
,通常推荐使用 wx.navigateTo 进行跳转,以便返回原页面 , 以提高加载速度 。当页面特别多时 ,则不推荐使用
。
参数表如下所示:
wx.navigateTo({
url: 'test?id=1',
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
acceptDataFromOpenedPage: function(data) {
console.log(data)
},
someEvent: function(data) {
console.log(data)
}
...
},
success: function(res) {
// 通过eventChannel向被打开页面传送数据
res.eventChannel.emit('acceptDataFromOpenerPage', { data: 'test' })
}
})
流程图如下:
重定向 ,当页面过多时,被保留页面会挤占微信分配给小程序的内存 ,或是达到 微信所限制的 10 层页面栈 的情况下, 我们应该考虑选择 wx.redirectTo
wx.redirectTo() 用于关闭当前页面 ,跳转到应用内的某个页面
这样的跳转 , 可以避免跳转前页面占据运行内存 , 但返回时页面需要重新加载 , 增加了返回页面的显示时间
参数表如下所示:
wx.redirectTo({
url: 'test?id=1'
})
流程图如下:
跳转到 tabBar 页面 ,并关闭其他所有非 tabBar 页面
参数表如下所示 :
wx.navigateBack() 用于关闭当前页面, 并 返回上—页面或多级页面
开发者可通过 getCurrentPages()获取当前的页面栈 ,决定需要返回几层则设置对象的 delta 属性 即可
参数表如下:
// 在C页面内 navigateBack,将返回A页面
wx.navigateBack({
delta: 2
})
关闭所有页面 , 打开到应用内的某个页面 , 返回的时候跳到首页
参数表如下所示:
wx.reLaunch({
url: 'test?id=1'
})
网页开发 , 渲染线程和脚本是互斥的 , 这也是为什么长时间的脚本运行可能会导致页面失去响应的原因 , 本质就是我们常说的 JS是单线程的
而在小程序中 , 选择了 Hybrid 的渲染方式 ,将视图层和逻辑层是分开的, 双线程同时运行 :
渲染层 : 界面渲染相关的任务全都在 webview 线程里执行 。-个小程序存在多个界面 , 所以渲染层存在多个 webview 线程
逻辑层 : 采用 JsCore 线程运行 JS 脚本 , 在这个环境下执行的都是有关小程序业务逻辑的代码
小程序在渲染层, 宿主环境会 把wxml 转化成对应的JS对象
在逻辑层发生数据变更的时候,通过宿主环境提供的 setData 方法 把数据从逻辑层传递到染层,再经过对比前后差异,把差异应用在原来的 Dom 树上,染出正确的视图
当视图存在交互的时候,例如用户点击你界面上某个按钮,这类反馈应该通知给开发者的逻辑层,需要将对应的处理状态呈现给用户
对于事件的分发处理,微信进行了特殊的处理
,将所有的事件拦截后,丢到逻辑层交给 JavaScript 进行处理
由于小程序是基于双线程的 ,也就是任何在视图层和逻辑层之间的数据传递都是线程间的通信, 会有-
定的延时, 因此在小程序中 ,页面更新成了异步操作
异步会使得各部分的运行时序变得复杂-些, 比如在渲染首屏的时候 ,逻辑层与渲染层会同时开始初始
化工作 , 但是渲染层需要有逻辑层的数据才能把界面渲染出来
如果渲染层初始化工作较快完成 , 就要等逻辑层的指令才能进行下-步工作
因此逻辑层与渲染层需要有一定的机制保证时序正确 , 在每个小程序页面的生命周期中 , 存在着若干次
页面数据通信
小程序启动运行两种情况:
冷启动 (重新开始) :用户首次打开或者小程序被微信主动销毁后再次打开的情况 , 此时小程序需
要重新加载启动, 即为冷启动
热启动 : 用户已经打开过小程序 , 然后在-定时间内再次打开该小程序 , 此时无需重新启动 , 只需
要将后台态的小程序切换到前台, 这个过程就是热启动
开发者在后台发布新版本之后 , 无法立刻影响到所有现网用户 , 但最差情况下 , 也在发布之后 24 小时之
内下发新版本信息到用户
每次冷启动时 ,都会检查是否有更新版本 ,如果发现有新版本 , 将会异步下载新版本的代码包, 并同时
用客户端本地的包进行启动, 即 新版本的小程序需要等下一次冷启动才会应用上
小程序启动会常常遇到如下图场景 :
这是因为 ,小程序首次启动前 ,微信会在小程序启动前为小程序准备好通用的运行环境 ,如运行中的线程和 一些基础库的初始化
然后才开始进入启动状态 ,展示一个固定的启动界面 ,界面内包含小程序的图标名称和加载提示图标 。
此时 , 微信会在背后完成几项工作 :
下载到的小程序代码包不是小程序的源代码 , 而是编译 、压缩 、打包之后的代码包
整体流程如下图:
围绕上图小程序的启动流程我们可以从:
两个纬度进行切入。
提升体验最直接的方法是 控制小程序包的大小 , 常见手段有如下:
采取分包加载的操作, 将用户访问率高的页面放在主包里 ,将访问率低的页面放入子包里 ,按需加载
当用户点击到子包的目录时 , 还是有一个代码包下载的过程 , 这会感觉到明显的卡顿 , 所以 子包也不建议拆的太大
当然我们可以采用 子包预加载技术 , 并不需要等到用户点击到子包页面后在下载子包
关于微信小程序首屏渲染优化的手段如下:
在微信小程序中 ,提高页面的多次渲染效率主要在于 正确使用setData
除此之外 , 对于 -些独立的模块我们尽可能抽离出来,这是因为 自定义组件的更新并不会影响页面上其他元素的更新
各个组件也将具有各自独立的逻辑空间 。每个组件都分别拥有自己的独立的数据 、 setData 调用