未验证 提交 2d6d12fa 编写于 作者: W wanganxp 提交者: GitHub

Update performance.md

上级 2f51baa2
#### 运行原理
1. 逻辑层和视图层分离,且非H5端通信有折损
##### 逻辑层和视图层分离,且非H5端通信有折损
``uni-app`` 在非H5端运行时,从架构上分为逻辑层和视图层两个部分。逻辑层负责储存数据和执行业务逻辑,视图层负责页面渲染。
``uni-app`` 在非H5端运行时,从架构上分为逻辑层和视图层两个部分。逻辑层负责执行业务逻辑,也就是运行js代码,视图层负责页面渲染。
页面加载时,联网和逻辑运算在逻辑层(Android是v8,iOS是jscore),然后会传递数据给视图层渲染。这种通信有损耗。同样,在视图层操作时,比如拖动页面,要实时传递事件给逻辑层接收,也是有损耗的
虽然开发者在一个vue页面里写js和css,但其实,编译时就已经将它们拆分了
2. App端渲染引擎可切换
###### 逻辑层详解
在App端,nvue页面的视图层是由原生引擎渲染的,vue页面的视图层是os的webview渲染的。
uni-app的webview渲染经过优化,性能也足够好。它比nvue弱的地方主要在于启动速度和可左右拖动的长列表。
逻辑层是运行在一个独立的jscore里的,它不依赖于本机的webview,所以一方面它没有浏览器兼容问题,可以在Android4.4上跑es6代码,另一方面,它无法运行window、document、navigator、localstorage等浏览器专用的js API。
3. app-vue和小程序的数据更新,分页面级和组件级
`jscore`就是一个标准js引擎,标准js是可以正常运行的,比如if、for、各种字符串、日期处理等。js和浏览器的区别要注意区分开来。
- 所谓浏览器的js引擎,就是jscore或v8的基础上新增了一批浏览器专用API,比如dom;
- node.js引擎,则是v8基础上补充一些电脑专用API,比如本地io;
- 那么uni-app的App端和小程序端的js引擎,其实是在jscore上补充了一批手机端常用的JS API,比如扫码。
###### 视图层详解
h5和小程序平台,以及app-vue,视图层是webview。而app-nvue的视图层是基于weex改造的原生视图。
在iOS上,所有人都只能使用iOS提供的webview。它有一定的浏览器兼容问题,iOS版本不同,它的表现有细微差异。
Android上小程序大多自带了一个几十M的chromium webview,而App端没办法带这么大体积的三方包,所以App端使用了Android system webview,而系统webview跟随手机不同而有差异。
所以uni-app的js基本没有不同手机的兼容问题(因为js引擎自带了),而视图层的css,在app-vue上会有手机浏览器的css兼容问题。所以在app-vue的场景中尽量不要使用太新的css语法,除非你不打算支持低端机。
###### 逻辑层和视图层分离的利与弊
逻辑层和视图层分离,好处是js运算不卡渲染,最简单直接的感受就是:窗体动画稳。
如果开发者使用过5+App,应该有概念,webview新窗体一边做进入动画,一边自身渲染,很容易卡动画。而uni-app则无需写预载代码,新窗体渲染快且动画稳定。
但是两层分离也带来一个坏处,这两层互相通信,其实是有损耗的。
iOS还好,但Android低端机上,每次通信都要耗时几十毫秒。平时看不出来影响,但有几个场景表现明显。
1. 连续高帧率绘制canvas动画,会发现还不如webview内部绘制流程
2. 视图层滚动、跟手操作,不停反馈给逻辑层,js再处理逻辑并通知视图层做对应更新。此时会发现交互不跟手或卡
不管app-vue/小程序,还是app-nvue,都有相同的问题。
解决这类问题,在webview渲染和原生渲染引用了不同的做法。
- webview渲染的视图层
在app-vue和微信小程序上,提供了一种运行于视图层的专属js,微信叫做wxs,uni-app也沿用了这个名称。
微信里对wxs限制较多,只能实现有限的功能,app端(尤其是v3编译器下)则没有限制。
wxs中可以监听手势,以uni ui的swiperAction组件为例,手指拖动,侧边的列表菜单项要跟手滑出,此时就需要使用wxs才能实现流畅效果。
至于canvas动画,微信的canvas是原生的,无法运用wxs操作,且一样有通信折算,所以绘制动画的性能不佳。而uni-app的app-vue的canvas是webview的,并且支持wxs操作,开发者可以在普通js中传递数据和指令给wxs,在wxs里绘制动画,将不再有通信折损,实现更流畅的效果(app端需v3编译器)
- 原生渲染的视图层
在app-nvue里,折损一样存在。包括react native也有这个问题。weex发明了一套bindingx机制,可以在js里传一个表达式给原生,由原生解析后根据指令操作视图层,这个技术在uni-app里也可以使用。
bindingx作为一种表达式,它的功能不及js强大,但基本的手势监听、动画还是可以实现的,比如uni ui的swiperAction组件在app-nvue下运行时会自动启用bindingx,以实现流畅跟手。
###### app-vue和小程序的数据更新,分页面级和组件级
对于复杂页面,更新某个区域的数据时,需要把这个区域做成组件,这样更新数据时就只更新这个组件,否则会整个页面的数据更新,造成点击延迟卡顿。
这就是自定义组件编译模式的特点。
比如微博长列表页面,点击一个点赞图标,赞数要立即+1,此时这个点赞图标一定要做成组件。否则这个+1会引发页面级所有数据的更新。
比如微博长列表页面,点击一个点赞图标,赞数要立即+1,此时这个点赞按钮一定要做成组件。否则这个+1会引发页面级所有数据的更新。
app-nvue和h5不存在此问题。造成差异的原因是小程序目前只提供了组件差量更新的机制,不能自动计算所有页面差量。
......@@ -45,7 +92,7 @@ app-nvue和h5不存在此问题。造成差异的原因是小程序目前只提
##### 长列表
- 长列表中如果每个item有一个点赞按钮,点击后点赞数字+1,此时点赞组件必须是一个单独引用的组件,才能做到差量数据更新。否则会造成整个列表数据重载。(要求自定义组件模式)
- 长列表中每个item并不一定需要做成组件,取决于你的业务中是否需要差量更新某一行item的数据,如没有此类需求则不应该引入大量组件。(点击item后背景变色,属于css调整,没有更新data数据和渲染,不涉及这个问题)
- app端nvue的长列表应该使用list组件,有自动的渲染资源回收机制。vue页面使用页面滚动的性能,好于使用scroll-view的区域滚动。
- app端nvue的长列表应该使用list组件,有自动的渲染资源回收机制。vue页面使用页面滚动的性能,好于使用scroll-view的区域滚动。uni ui封装了uList组件,强烈推荐开发者使用,避免自己写的不好产生性能问题。
- 如需要左右滑动的长列表,请在HBuilderX新建uni-app项目选新闻模板,那是一个标杆实现。自己用swiper和scroll-view做很容易引发性能问题。
##### 减少一次性渲染的节点数量
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册