| 导语 “一次编码,处处运行”一直是程序员的理想,最近研究了一下NativeScript的原理,对比了一下NS和RN的区别。
一、NativeScript原理
NativeScript是一个基于Apache 2.0许可的Github开源项目。既不是一种新型的JavaScript语言,也不是原生功能的封装器。NativeScript 的思路就是使用移动平台的 JavaScript 引擎来进行跨平台开发。逻辑部分自然无需多说,关键在于如何使用平台特性,JavaScript 要怎样才能调用 native 的东西呢。NativeScript 给出的答案是通过反射得到所有平台 API,预编译它们,然后将这些 API 注入到 JavaScript 运行环境,接下来在 Javascript 调用后拦截这个调用,并运行 native 代码,整体架构如下图所示:
NativeScript包括一个JavaScript运行时环境和一种将JavaScript调用转化为原生调用的机制。用JavaScript(或TypeScript,CoffeeScript等)语言编写应用,之后在安卓平台用V8,在iOS和Windows Phone上用WebKit JavaScriptCore解释应用。然后,NativeScript运行时环境找到原生的目标API,将JS数据类型转化为相应的原生类型,然后调用原生API,并将得到的结果值返回,具体流程如下图所示:
举例来说,在安卓平台上创建文件对象var file = new java.io.File(path);的步骤如下:
据Telerik介绍,与纯原生代码相比NativeScript运行时环境会带来大概10%的性能损失。
NativeScript可以将其所支持平台上的任意原生API作为目标,包括传感器接口API和用Objective C,Java或.NET编写的第三方库。UI组件是原生的,UI事件由在JavaScript代码中声明的原生处理程序处理,如View.OnClickListener,UIControl.addTarget。
为了避免开发者需要对三个支持的平台有深入的理解,该框架包含了一个抽象与原生代码连接的NativeScript模块层(NativeScript Modules Layer,NML),可以自动将JavaScript调用转化为原生调用。NML包含如下模块:Application,Camera,Color,Console,Data,File System,HTTP,Imaging,Local Settings,Location,Timer,UI。开发者并未受限于只能使用NML,也可以访问任意原生API。
二、NativeScript和RN区别
2.1、页面结构
NativeScript:主推的是用javascript语言写逻辑+XML写布局来实现跨终端App(即iOS、Android、WP),NS一个页面的目录结构:
RN:一个页面一般就是一个JS文件,样式、XML、JS全部写在一个文件里:
2.2、是否支持与原生混合开发
NativeScript 和 React Native 在侧重点上有很大的不同,使得这两个产品目前走向了不同的方向:
所以对于与原生混合开发,RN和NS区别如下:
RN:支持,可以随时打开AndroidStuido/Xcode修改原生代码,甚至可以往一个现有的Android/iOS项目中添加RN的支持
NativeScript:NativeScript和React不同,无法与原生项目融合,即你只能纯写个NativeScript的应用,基本不可能把它抽离出来作为某原生应用的一部分来出现。NS官网也提出将NativeScript嵌入现有的iOS应用程序是一项实验性功能(https://docs.nativescript.org/integration-with-existing-ios-and-android-apps/extend-existing-android-app)。
2.3、社区资源
RN:比较丰富,网上N多相关学习介绍文章,有非常丰富的中文学习资源
NativeScript:学习资源较为匮乏,一般只能从官网学习
2.4、是否有成熟的产品在使用
RN:RN目前有很多成熟的产品的产品在使用,社区资源丰富,上架的产品比较多。
NativeScript:因为成熟度不够,目前没有发现成熟的产品在使用,在社区上部分开发者也表示适合小团队或者个人开发者使用。
2.5、组件支持
RN:RN在组件支持上虽然也不是很完善,但是给了开发者很大空间可以自定义,同时因为RN的实现原理,可以很方便的设置相应组件的属性
NativeScript:组件支持不够完善,NativeScript中虽然已经支持了很多组件,比如说tabview、srcollview、button,但是提供的组件方法、属性过少,整个框架还不是很丰满。举个例子,Button按钮我们肯定会经常给它设定背景,即图片按钮。比如下面这个:
原生应用里,iOS/Android里可以用属性进行设置,前端用background-image也行。但是目前NativeScript里面Button是没办法设置背景的,所以要想实现这个按钮,只能使用图片,所以上面那个按钮在NativeScript中XML布局里面的代码是这样的:
<GridLayout row="0" col="0" cssClass="crossBtn">
<Image url="~/app/images/cross-btn.png" stretch="fill" />
</GridLayout>
最外层封个Layout然后让图片填充。再举几个例子:文字不能加粗、不能更改字体;Label组件周边有一圈儿Margin始终干不掉;Search组件外层有灰色底色等。而且组件对于系统调用也不是很好,在论坛看到不少开发者反馈如何调用通讯录,目前系统调用就支持照相机、文件、定位。
2.6、生成的APK体积
RN:HelloWorld项目大约7M多
NativeScript:HelloWorld项目大约12M多
---------------------------------------------------------------
原文作者,腾讯工程师Red。