除了一系列的交互式动画能力之外,我们还利用 的优势,提供了很多高级功能。
1.提供网格视图瀑布流组件
瀑布流是常用的列表布局方式,得益于布局过程中的可控性,我们在底层直接实现并提供,渲染性能比CSS更好。
2.提供截图组件
大部分小程序都是基于实现自定义分享图片的功能,一方面需要通过绘制指令手动实现,繁琐;另一方面当分享图片布局复杂,或者做长图的时候会受限于系统的尺寸限制,方案的实现成本会很高。得益于渲染流程的可控性,WXML子树是可以直接截图的,所以我们直接提供了截图组件,可以复用更完备的WXSS能力,大大降低开发成本。
3.-view组件支持列表反转
在聊天对话场景中,列表是反向滚动的(从底部往顶部滚动),如果用正向滚动来模拟,会有很多冗余逻辑,而且容易跳转,-view提供的属性可以很好的解决这个问题。
计划中还有更多功能,请参阅功能状态了解详情。
响应数据绑定
框架的核心是一个响应式的数据绑定系统,可以非常轻松地保持数据与视图同步。修改数据时,只需要在逻辑层修改数据,视图层就会相应更新。
我们来看这个简单的例子:
小程序的架构模型不同于传统的Web单线程架构,小程序采用的是双线程架构。
微信小程序的渲染层和逻辑层分别由两个线程管理,渲染层使用界面渲染的方式;逻辑层使用运行中的代码。
Hello {{name}}! Click me!
// This is our App Service. // This is our data. var helloData = { name: 'Weixin' } // Register a Page. Page({ data: helloData, changeName: function(e) { // sent data change to view this.setData({ name: 'MINA' }) } })
页面管理
框架管理整个小程序的页面路由,实现页面之间的无缝切换,并赋予页面完整的生命周期。开发者只需将页面的数据、方法、生命周期函数注册到框架中,其他所有复杂操作都交由框架处理。
基本组件
框架提供了一套自带微信风格样式和特殊逻辑的基础组件,开发者可以通过组合基础组件来打造功能强大的微信小程序。
丰富的API
框架提供了丰富的微信原生API,可以轻松调用微信提供的能力,比如获取用户信息、本地存储、支付功能等。
2. 双线程与单线程比较
在单线程架构下,也就是传统HTML开发中,官方建议将js加载到body下面。为什么建议插在下面呢?是因为单线程阻塞问题。因为HTML文件是从上往下渲染的,如果在中间插入js,会打断HTML节点渲染,转而执行js。js执行完之后,节点会继续渲染。是因为单线程阻塞问题,所以建议插在下面,用.就可以获取到已经渲染好的节点。
这种情况当然可以通过一些手段来避免,比如,等,添加这两个属性之后,虽然不会阻塞DOM渲染,但是并没有从根本上解决问题,而只是合理安排资源解析而已。
单线程阻塞问题还没结束,另一个问题来了,如果所有资源都通过请求来获取,不但会阻塞 JS 解析时间,还会增加 JS 请求时间。如果请求 JS 资源时间不可控怎么办?这时候另一个选择就至关重要了,那就是缓存。微信在这方面做的很好,那就是微信 SDK 就是一系列的集合,提供了微信丰富的原生能力以及微信内部的方法。
我们在开发微信公众号h5的时候,需要手动在自己的项目中注入一定版本的微信SDK。这种方式并没有提供很好的用户体验,因为在加载js、解析js逻辑的时候,会占用渲染资源。原因就是上面刚刚说的单线程阻塞问题。如果我们有一个接收平台,比如微信客户端,那么我们可以把微信SDK等资源放在客户端,在加载页面的时候,逐层到view层动态注入。这种方式的好处是显而易见的,一是会减少包的大小,二是减少发送的网络请求次数。
小程序中也会用到微信 SDK,当然不止微信 SDK 这样处理,它是分层注入双线程的,底层基础库也是提前放在层中,在页面加载时动态注入。比如说,如果公司给你提供电脑来开发项目,以前员工来公司上班需要自带开发工具,如果公司提供统一的开发工具,那你就不用再带电脑来公司上班了,减少了每个员工上班需要提前准备的资源。
可以看出双线程带来的好处不只是一分为二,更重要的是有了一个强大的层来支撑。层除了做一些资源的动态注入,还负责很多事情,比如请求转发、离线存储、组件渲染等。界面以成熟的 Web 技术渲染为主,辅以大量接口提供丰富的客户端原生能力。同时每个小程序页面渲染方式不同,可以提供更好的交互体验,更贴近原生体验,避免单一任务负担过重。另外,界面渲染也定义了一套内置组件来统一体验,并提供一些基础的、通用的能力,进一步降低开发者的学习门槛。值得一提的是,一些比较复杂的内置组件由客户端原生渲染,提供更好的性能。
3.传统h5开发的弊端
使用 Web 技术渲染小程序存在一些不可控因素和安全风险。这是因为 Web 技术非常开放灵活,我们可以随意使用脚本跳转网页或者更改界面上的任何内容。此时安全问题就被摆到了微信团队的台面上。如果微信小程序可以离线浏览,小程序开发者只需要在本地缓存一些应用数据,然后使用脚本将小程序渲染跳转到其他在线网页上,那么体验会非常糟糕。相信前端开发者对这个操作一定非常熟悉。
另外,通过操作DOM,可以直接获取小程序内部的一些敏感数据,比如用户信息,商户信息等,那么小程序就完全没有安全性了。
为了解决安全管控问题,小程序会禁止开发者使用浏览器提供的一些开放接口,比如页面跳转、DOM操作、动态脚本执行等。如果把这些东西一一禁用,必然会进入恶性循环,因为太过灵活、浏览器接口太丰富,很容易遗漏一些危险的接口,而即便把危险的接口全部禁用,也必然无法阻止浏览器内核的下一次更新,一些漏洞可能又会再次出现。
因此要彻底解决这个问题,必须提供一个沙盒环境来运行开发者的代码。这个沙盒环境不能有任何浏览器相关的接口,只提供纯解释执行环境。 和 等特性满足这个条件,都可以让另一个线程执行。但是考虑到小程序是多架构的,每个小程序页面渲染后显示效果都不一样,在这种架构下,用某一个来管理所有的小程序页面并不容易。
4. 后处理小程序逻辑层应用
小程序开发框架逻辑层通过引擎为开发代码和微信小程序特有的功能提供运行环境。
逻辑层对数据进行处理并发送给视图层,同时接收视图层的事件反馈。
开发者编写的所有代码最终都会被打包成一个文件,在小程序启动时运行,直到小程序销毁,这种行为类似,所以逻辑层也叫App。
在此基础上,我们增加了一些功能,方便用户开发小程序:
注意:小程序框架的逻辑层并不运行在浏览器中,所以Web中的某些功能无法使用,如等。
小程序运行环境
微信小程序运行于多个平台:iOS/微信客户端、微信客户端、PC微信客户端、Mac微信客户端、小程序硬件框架、以及用于调试的微信开发者工具等。
在不同的运行环境下,脚本的执行环境和组件渲染所用的环境不同,表现也不同:
无法启用JIT编译(Just-In-Time),同等条件下的运行性能明显低于其他平台。
平台差异
尽管运行时非常相似,但仍存在一些细微的差别:
开发者工具仅供调试使用,最终性能以客户为准。
支持操作限制
由于安全原因,小程序不支持动态执行JS代码,即:
标准支持
不同平台的小程序的JS执行环境不同,从而导致不同平台对标准的支持存在差异。
为了尽可能抹平这些差异,小程序基础库内置了 core-js,可以填补平台环境下缺失的标准 API。

需要注意的是,平台对于语法的支持差异是无法消除的,当需要使用一些高级语法时,比如,就需要使用对这些语法的支持。
无法
以下API在某些低版本客户端无法使用,请尽量避免使用
与标准的差异 时间差异
由于实现原因和iOS的限制,iOS环境采用模拟方式,也就是说触发的任务是普通任务,而不是微任务,这导致iOS和标准在时间上有差异。
var arr = [] setTimeout(() => arr.push(6), 0) arr.push(1) const p = new Promise(resolve => { arr.push(2) resolve() }) arr.push(3) p.then(() => arr.push(5)) arr.push(4) setTimeout(() => arr.push(7), 0) setTimeout(() => { // 应该输出 [1,2,3,4,5,6,7] // 在 iOS 小程序环境,这里会输出 [1,2,3,4,6,5,7] console.log(arr) }, 1000)
关于普通任务和微任务的区别可以参考这篇文章
如何确定当前环境中需要哪些代码转换目标
具体小程序基础库版本有最低微信客户端版本要求,例如基础库 v2.15.0 要求 版本最低为 7.0.22,iOS 版本最低为 7.0.20。
特定客户端版本有最低操作系统版本要求,例如 iOS 7.0.20 至少需要 iOS 10。
因此,当指定具体的小程序基础库版本(可在小程序管理页【设置】-【基础设置】-【最低基础库版本设置】中设置)时,我们可以获取所需支持的最低执行环境。
具体数据可以从这个开源库中获取。
小程序运行机制 1.小程序生命周期
小程序从启动到最终销毁,会经历很多不同的状态,在不同的状态下小程序的表现也会有所不同。
1.1 小程序启动
从用户认知的角度来说,小程序的启动大致可以分为两种情况:冷启动和热启动。
从小程序生命周期来看,我们一般所说的“启动”是冷启动,热启动一般是指从后台切换到前台。
1.2 前后端
小程序启动后,界面展示给用户,小程序处于“前台”状态。
当用户“关闭”小程序时,小程序并没有真正关闭,而是进入了“后台”状态。此时小程序还能运行一小段时间,但部分API的使用会受到限制。切换到后台的方式包括但不限于以下几种:
当用户再次进入微信,打开小程序时,小程序就会回到“前台”状态。
1.3 暂停
小程序进入“后台”状态一段时间后(目前为5秒),微信会停止小程序JS线程的执行,小程序进入“暂停”状态。此时小程序的内存状态会保留,但是开发者代码执行会停止,当小程序再次进入“前台”时才会触发事件和接口回调。
当开发者使用后台音乐播放、后台地理定位等能力时,小程序能够继续在“后台”运行,不会进入“暂停”状态。
1.4 小程序销毁
如果用户长时间没有使用小程序,或者系统资源紧张,小程序就会被“销毁”,也就是彻底停止运行。具体包括以下几种情况:
基础库1.1.0及以上,1.4.0及以下版本:当用户通过扫一扫、转发等入口(场景值1007、1008、1011、1025)进入小程序,未置顶退出小程序时,小程序将会被销毁。
2. 小程序冷启动页面
小程序冷启动时,打开的页面有以下几种情况
2.1 重启策略
从基础库2.8.0开始支持,需要兼容低版本。
小程序冷启动时,若无路径启动(A类场景),会默认进入小程序首页。在该页面对应的json文件中(也可以在app.json节全局配置),指定配置项可以改变这个默认行为,使得退出某个页面后,A类场景下次冷启动可以回到这个页面。
代码示例:
{ "restartStrategy": "homePage" }
可能的值:
注意:即使不配置,如果小程序退出时间过长(目前默认是一天,可以使用退出状态进行调整),下次冷启动将不再按照配置进行,而是直接从首页启动。
无论如何,页面的状态都不会被保留,比如输入框内的文本内容,复选状态等,如果需要恢复或者部分恢复,就需要使用退出状态。
3.小程序热启动页
小程序热启动时,打开的页面有以下几种情况
A类场景中常见的场景值有以下几种:
4. 退出状态
从基础库2.7.4开始支持,需要兼容低版本。
每当小程序被销毁时,页面回调函数都会被调用,如果想保留页面的状态,可以把一些数据“保存”在这个回调函数中,下次启动时就可以获取这些保存的数据。
代码示例:
{ "restartStrategy": "homePageAndLatestPage" }
Page({ onLoad: function() { var prevExitState = this.exitState // 尝试获得上一次退出前 onSaveExitState 保存的数据 if (prevExitState !== undefined) { // 如果是根据 restartStrategy 配置进行的冷启动,就可以获取到 prevExitState.myDataField === 'myData' } }, onSaveExitState: function() { var exitState = { myDataField: 'myData' } // 需要保存的数据 return { data: exitState, expireTimeStamp: Date.now() + 24 * 60 * 60 * 1000 // 超时时刻 } } })
返回值可以包含两项:
更完整的示例:在开发者工具中预览效果
防范措施
参考: