跨端方案

2,280 阅读4分钟

0 综述

跨端的目的

跨端,目的很明确,就是用一处代码开发,覆盖到 IOS、android、h5 的平台上,就能提高开发效率。如果这处开发对前端或者客户端开发人员学习成本低,就更好了。

跨端要实现的主要能力

  1. 如何把跨端代码变成各端上的界面
  2. 如何响应界面上的交互
  3. 如何使跨端代码调用端的能力

跨端要面临的主要问题

  1. 界面性能
  2. 开发效率、上手难度
  3. 动态化,即不发版能否动态更改界面内容(对IOS尤为重要)

三波主流方案

历史的长河中,跨端经历了三波主流的方案。

技术类型 渲染方式 性能 开发效率 动态化 框架代表
Hybrid webview Ionic
js+原生渲染 原生控件 较好 React-natice、Weex
自绘UI 系统API 一般 Flutter

1 混合应用

在早期,对于交互要求不高的类似活动页这种需求,通常采用Hybrid开发。

思路

image
客户端提供一个类似浏览器的webview壳子,直接获取线上的h5页面展示。通过客户端提供的api进行交互和端能力调用。

优势

  • 动态化,只要改了资源地址的web页面内容,就等于改了跨端页面
  • 开发成本特别低

问题

  • 性能不好
  • 原生能力有限 本质上,混合应用算不上跨端方案。

2 真正的跨端

回到跨端的目的,什么是真正的跨端呢?就是一套代码,在不同平台下真正落地成了平台的原生控件。这就是 js+原生渲染 提供的能力。

思路

image

  • 跨端代码通过工具打包成js后,发布到服务器上
  • 原生端上去拉,提供js环境跑起来,包上框架,调用bridge绘制UI、进行页面交互

跨端代码

适逢这套方案发家时,也是MVVM最蓬勃发展的阶段,因此前端产生了五花八门的模式,比如以RN为代表的React风格和以Weex为代表的Vue风格。以RN为例,基于React的设计理念,前端程序员可以无差别的用React写跨端代码部分。
但不论写法如何,最终产生的都是一个js文件,这个文件里包含了所有UI组件声明、事件监听、原生能力调用等等。

端上提供的能力

js执行环境

首先,得让js跑起来

framework

然而仅仅写出React是不够的,我们需要框架把它跑起来。在web开发中,React框架往往是和React代码一起打包成js,再放到浏览器里执行的。
但相比于我们动不了的浏览器,在跨端方案中,我们有能力也必须在端上做些动作。既然如此,为了让js包更轻量也更稳定,索性就把框架层放到端的 JS Core 中。
这层框架和web中的react没有本质区别,都是根据react代码,创建虚拟DOM,管理生命周期,做diff,最终在必要的时候 patch 出节点操作命令。

bridge

从framework下来,至少有三件事需要和端交流:

  • 从 js patch 到端的控件操作命令(增删改),这是落地到原生控件的基础
  • 端上原生控件触发事件,需要向 js 通知
  • js 需要调用端上的能力

这个工作则需要 bridge 来做。

优势

  • 既能享受原生控件的性能
  • 又能享受动态化的发布

问题

  • 毕竟还有一层 JS Core,性能还是和原生有差距
  • bridge需要持续维护,也不能做到完美

3 更下一层

我们此前大费周章的写跨端代码,再包起来,还需要在各平台建立抹平的SDK,只为了把跨端代码转成原生控件。 后来,Flutter出来了,他说,我们不用原生控件了,直接自己画UI吧。

思路

Flutter完全抛弃了转原生控件再渲染的思路,直接建立了一套自己的体系。

Engine

直接对接平台UI绘制能力,在系统api层抹平了 IOS、android 的平台差异。

Framework

对标原生控件,建立层次分明的健全控件体系

优势

  • 性能:彻底抛弃了中间的各种繁琐层,性能对标原生
  • Dart语言,提供统一的开发标准

问题

  • 动态化:编译到AOT以后,很难做,难道要回到 webview 阶段?