当我们使用 uni-app 开发应用时,会发现想要实现一个高性能的下拉刷新或滑动删除效果,动画经常会非常卡顿。
为什么会卡顿呢?这个和 uni-app(vue)的实现原理有关。
因为 uni-app 在大部分平台实现思路和微信小程序一致,所以我们这里以微信小程序为例看一下:
微信小程序的渲染层和逻辑层分别由 2 个线程管理。
之所以分为逻辑层和渲染层,主要是为了管控,让开发者的代码只运行在逻辑层。
渲染层的界面使用了 WebView 进行渲染;逻辑层采用 JsCore 线程运行 JS 脚本。一个小程序存在多个界面,所以渲染层存在多个 WebView 线程,这两个线程的通信会经由 Native(微信客户端)做中转,逻辑层发送网络请求也经由 Native 转发。
由于交互动画,需要渲染层高频率的触发事件,逻辑层接收事件后,又需要把事件处理后的结果传递给渲染层,从而产生交互动画。
这中间频繁的通信,是影响性能的主要原因。
So,知道原因后,我们看下,uni-app/微信小程序是如何解决这个问题的。
解决方案:
我们核心思路就是减少通信,让开发者部分受管控代码能够运行在视图层,于是就有了 WXS,因为 WXS 是运行在渲染层的逻辑代码,所以和原始的逻辑层与渲染层通信的方式会不一样,这个后面会有专门的介绍。
WXS 入门指南
哪些平台支持 WXS
uni-app 的 WXS 目前支持以下几端:微信小程序、QQ 小程序、App-vue、h5。
使用 WXS 的一些限制:
- 目前只能响应内置组件事件、不支持自定义组件事件;
- 目前还不支持原生组件的事件、input 和 textarea 组件的 bindinput 事件;
- 只能使用 setStyle 和 setClass 进行动画设置。
目前字节跳动、百度、支付宝小程序所使用的 SJS
,大部分都是配合模板使用,能支持更多渲染场景和优化渲染性能。
但是相比于 WXS 会有一些限制:
- 只能外部引用,不支持内联;
- 函数不能作为组件事件回调。
也就是说,目前,SJS 可以实现一些高性能的模板渲染解析,但是不能用于实现高性能动画。
如何使用 WXS
支持内联和外部引用
1 | <!-- 内联 --> |
有几个要注意的点
- module 所指定的模块名不可与 data、methods、computed 内的属性重名;
- nvue 不支持 wxs,建议使用 bindingx。
WXS 事件通讯
组件事件监听、change:prop 与 callMethod 是组件/页面 与 wxs 模块双向通讯方式。
如上图所示,通讯流程如下
- 首先在页面/组件,注册事件处理函数,绑定 prop 和 propChange 处理函数;
- 然后页面/组件修改 data 触发 change:prop;
- wxs 响应 change:prop 事件,进行一些初始化操作;
- 用户操作页面,wxs 响应注册事件,调用 setClass、setStyle 修改动画属性;
- 完成状态迁移后,调用 callMethod 或 triggerEvent 进行状态处理。
需要注意的点
- callMethod、triggerEvent 参数不允许设置 function,所以无法通过传递回调函数,进行回调操作,可以通过 change:prop 完成相关回调通知。
WXS 使用示例
touchmove 事件监听、prop:change 监听
1 | <template> |
那今天关于 WXS 的入门指南就到这啦,想了解更多详细信息,可以参考下面的官方文档:
- 微信 wxs 官方文档(语法): https://developers.weixin.qq.com/miniprogram/dev/reference/wxs/
- 微信 wxs 官方文档(响应事件):https://developers.weixin.qq.com/miniprogram/dev/framework/view/interactive-animation.html
- uni-app wxs 文档:https://uniapp.dcloud.io/frame?id=wxs