使用Uni-app开发APP

1、运行原理

uni-app 在非H5端运行时,从架构上分为逻辑层和视图层两个部分。逻辑层负责执行业务逻辑,也就是运行js代码,视图层负责页面渲染。

虽然开发者在一个vue页面里写js和css,但其实,编译时就已经将它们拆分。

逻辑层

运行在一个独立的jscore里的,它不依赖于本机的webview

  • 无法运行window、document、navigator、localstorage等浏览器专用的js API
  • jscore就是一个标准js引擎,标准js是可以正常运行的,uni-app的App端和小程序端的js引擎,其实是在jscore上补充了一批手机端常用的JS API
image.png

视图层

h5和小程序平台,以及app-vue,视图层是webview。而app-nvue的视图层是基于weex改造的原生渲染视图。

关于webview,iOS上默认是WKWebview,Android在APP端默认是Android system webview,因此app-vue会有手机浏览器的css兼容问题

逻辑层和视图层分离的利与弊

  • 窗体动画稳
    • js运算不卡渲染
  • 两层互相通信,有通信损耗
    • 不管小程序还是app,不管app-vue还是app-nvue,都有这个两层通信损耗的问题
  • 解决方案
    • webview渲染的视图层,提供了一种运行于视图层的专属js,详见:renderjs
    • 原生渲染的视图层,weex提供了一套bindingx机制,可以在js里一次性传一个表达式给原生层
    • 在app-vue和小程序,频繁更新数据的区域做成组件,以防止少量数据更新导致整个页面更新

优化建议

  • 使用nvue代替vue
  • 使用v3编译模式,fast启动模式
  • 避免使用大量大图
  • 优化数据更新,定义在data里面的数据尽量是视图层需要的
  • 减少一次性渲染的节点数量,比如分批加载数据
  • 减少组件数量、减少节点嵌套层级
    • 组件的设计策略:复用,频繁数据更新
  • 避免视图层和逻辑层频繁进行通讯
    • 减少 scroll-view 组件的 scroll 事件监听,当监听 scroll-view 的滚动事件时,视图层会频繁的向逻辑层发送数据;
    • 监听 scroll-view 组件的滚动事件时,不要实时的改变 scroll-top/scroll-left 属性,因为监听滚动时,视图层向逻辑层通讯,改变 scroll-top/scroll-left 时,逻辑层又向视图层通讯,这样就可能造成通讯卡顿。
    • 注意 onPageScroll 的使用,onPageScroll 进行监听时,视图层会频繁的向逻辑层发送数据;
    • 多使用css动画,而不是通过js的定时器操作界面做动画
    • 如需在canvas里做跟手操作,app端建议使用renderjs,小程序端建议使用web-view组件。web-view里的页面没有逻辑层和视图层分离的概念,自然也不会有通信折损。
  • 优化页面切换动画
    • 页面初始化时若存在大量图片或原生组件渲染和大量数据通讯,建议延时100ms~300ms
    • App-nvue和H5,还支持页面预载`uni.preloadPage

2、事件监听与页面通讯

uni.$emit(eventName,OBJECT)

触发全局的自定事件。附加参数都会 传给监听器回调。

属性 类型 描述
eventName String 事件名
OBJECT Object 触发事件携带的附加参数

代码示例

    uni.$emit('update',{msg:'页面更新'})
uni.$on(eventName,callback)

监听全局的自定义事件。事件可以由 uni.$emit 触发,回调函数会接收所有传入事件触发函数的额外参数。

uni.$once(eventName,callback)

监听全局的自定义事件。事件可以由 uni.$emit 触发,但是只触发一次,在第一次触发之后移除监听器。

属性 类型 描述
eventName String 事件名
callback Function 事件的回调函数

代码示例

    uni.$on('update',function(data){
        console.log('监听到事件来自 update ,携带参数 msg 为:' + data.msg);
    })

        uni.$once('login',function(data){
        console.log('监听到事件来自 login (只触发一次),携带参数 msg 为:' + data.msg);
    })
uni.$off([eventName, callback])

移除全局自定义事件监听器。

属性 类型 描述
eventName Array<String> 事件名
callback Function 事件的回调函数

Tips

  • 如果没有提供参数,则移除所有的事件监听器;
  • 如果只提供了事件,则移除该事件所有的监听器;
  • 如果同时提供了事件与回调,则只移除这个回调的监听器;
  • 提供的回调必须跟$on的回调为同一个才能移除这个回调的监听器;
uni.onUserCaptureScreen(CALLBACK)

监听用户主动截屏事件,用户使用系统截屏按键截屏时触发此事件。

平台差异说明

App H5 微信小程序 支付宝小程序 百度小程序 字节跳动小程序 QQ小程序
x x
uni.onNetworkStatusChange(CALLBACK)

监听网络状态变化。可使用uni.offNetworkStatusChange取消监听。

uni.offNetworkStatusChange(CALLBACK)

取消监听网络状态变化。

CALLBACK 返回参数

参数 类型 说明 平台差异说明
isConnected Boolean 当前是否有网络连接 字节跳动小程序不支持
networkType String 网络类型

3、关于 App 的调试debug

  • APP调试器

  • console.log打印日志

  • 同步断点到调试器代码调试

  • 如果是调试App的界面和常规API,推荐编译到H5端

4、 Weex 页面的渲染

参考:详解 Weex 页面的渲染过程

图中画出了 Weex SDK 的部分内容。其中 weex-vue-frameworkVue.js 是对等的,语法和内部机制都是一样的,只不过 Vue.js 最终创建的是 DOM 元素,而 weex-vue-framework 则是向原生端发送渲染指令,最终渲染生成的是原生组件。Weex Runtime 用来对接上层前端框架(如 Vue.js 和 Rax)并且负责和原生端之间的通信。Render Engine 就是针对各个端开发的原生渲染器,包含了 Weex 内置组件和模块的实现,可扩展。

5、Patch

image.png

在 Vue.js 内部,Web 平台和 Weex 平台中的 patch 方法是不同的,但是都是由 createPatchFunction 这个方法生成的,它支持传递 nodeOps 参数,在其中代理了所有 DOM 操作。在 Web 平台中 nodeOps 背后调用的都是 Web API,在 Weex 平台中则调用的是 Weex Runtime 提供的 Native DOM API。触发 DOM 渲染的入口一致,但是不同平台的实现方式不同。

image.png

上层前端框架调用了 Weex 平台提供的 Native DOM API 之后,Weex Runtime 会构建一个用于渲染的节点树,并将操作转换成渲染指令发送给客户端

目前来说渲染指令是基于 JSON 描述的,具体格式大致如下所示:

{
  module: 'dom',
  method: 'createBody',
  args: [{
    ref: '_root',
    type: 'div',
    style: { justifyContent: 'center' }
  }]
}

原生渲染器接收上层传来的渲染指令,并且逐步将其渲染成原生组件。


image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容