逻辑层和视图层分离,好处是 js 运算不卡渲染,最简单直接的感受就是:窗体动画稳。
如果开发者使用过 App,应该有概念,webview 新窗体一边做进入动画,一边自身渲染,很容易卡动画。而 uni-app 则无需写预载代码,新窗体渲染快且动画稳定。
但是两层分离也带来一个坏处,这两层互相通信,其实是有损耗的。
iOS 还好,但 Android 低端机上,每次通信都要耗时几十毫秒。平时看不出来影响,但有几个场景表现明显。
- 连续高帧率绘制 canvas 动画,会发现还不如 webview 内部绘制流畅
- 视图层滚动、跟手操作,不停反馈给逻辑层,js 再处理逻辑并通知视图层做对应更新。此时会发现交互不跟手或卡
不管小程序还是 app,不管 app-vue 还是 app-nvue,都有这个两层通信损耗的问题。
解决这类问题,在 webview 渲染和原生渲染引用了不同的做法:
- webview 渲染的视图层
在 app-vue 和微信小程序上,提供了一种运行于视图层的专属 js,微信叫做wxs。
wxs 中可以监听手势,以 uni ui 的 swiperAction 组件为例,手指拖动,侧边的列表菜单项要跟手滑出,此时就需要使用 wxs 才能实现流畅效果。还有插件市场里一些自定义下拉刷新的插件,通过 wxs 实现了更高的性能体验。
uni-app 支持把 wxs 编译到微信小程序、App 和 H5 中。
微信里对 wxs 限制较多,只能实现有限的功能。app 端提供了更强大的renderjs,并兼容到 H5 平台。
比如 canvas 动画,微信的 canvas 无法通过 wxs 操作,js 不停绘制 canvas 动画因通信折损而无法流畅。uni-app 的 app-vue 里的 canvas 对象设计在 webview 视图层的,通过 renderjs 可以在视图层直接操作 canvas 动画,将不再有通信折损,实现更流畅的效果,详见:renderjs
- 原生渲染的视图层
在 app-nvue 里,逻辑层和视图层的折损一样存在。包括 react native 也有这个问题。所以也千万别以为原生渲染就多么高级。
weex 提供了一套 bindingx 机制,可以在 js 里一次性传一个表达式给原生层,由原生层解析后根据指令操作原生的视图层,避免反复跨层通信。这个技术在 uni-app 里也可以使用。
bindingx 作为一种表达式,它的功能不及 js 强大,但手势监听、动画还是可以实现的,比如 uni ui 的 swiperAction 组件在 app-nvue 下运行时会自动启用 bindingx,以实现流畅跟手。
renderjs
renderjs
的主要作用有2个:
- 大幅降低逻辑层和视图层的通讯损耗,提供高性能视图交互能力
- 在视图层操作dom,运行 for web 的 js库
平台差异说明
App | H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 抖音小程序、飞书小程序 | QQ小程序 |
---|---|---|---|---|---|---|
√(2.5.5+,仅支持vue) | √ | x | x | x | x | x |
- nvue的视图层是原生的,无法运行js。但提供了bindingx技术来解决通信阻塞。详见
- 微信小程序下替代方案是wxs,这是微信提供的一个裁剪版renderjs。详见
- web下不存在逻辑层和视图层的通信阻塞,也可以直接操作dom,所以在web端使用renderjs主要是为了跨端复用代码。如果只开发web端,没有必要使用renderjs。
#使用方式
设置 script 节点的 lang 为 renderjs
<script module="test" lang="renderjs">
export default {
mounted() {
// ...
},
methods: {
// ...
}
}
</script>
具体内容详见官网:官方renderjs