跨平台框架与React Native基础
跨平台框架
什么是跨平台框架?
这里的多个平台一般是指 iOS 和 Android 。
为什么需要跨平台框架?
目前,移动开发技术主要分为原生开发和跨平台开发两种。其中,原生应用是指在某个特定的移动平台上,使用平台所支持的开发工具和语言,直接调用系统提供的 API 所开发的应用。
其优势体现在:
- 可以快速访问本平台的全部功能,比如摄像头、 GPS 等;
- 原生应用的速度快、性能高,而且可以实现比较复杂的动画和绘制效果,用户体验较好。
缺点也很明显,主要体现在:
- 开发成本较高,不同的平台必须维护不同的代码,人力成本也会随之增加;
- 有新的功能需要更新时,只能进行版本升级。
针对原生开发所面临的问题,目前已经诞生了许多跨平台框架
跨平台框架都有哪些?
根据其原理,主要分为三类:
- H5 + 原生( Cordova 、 Ionic 、微信小程序);
其主要原理就是将 APP 的一部分需要动态改变的内容通过 H5 来实现,通过原生的网页加载控件 WebView ( Android )或 WKWebView ( iOS )来加载。
- JavaScript 开发 + 原生渲染( React Native 、 Weex 、快应用);
采用 Web 技术栈,将 DOM 映射为原生控件树,体验好,接近原生。
- 自绘 UI + 原生( Flutter );
实现了一个自绘引擎,使用自身的布局、绘制系统,所以不同平台效果能高度统一。
Flutter 简介
Flutter is Google’s portable UI toolkit for building beautiful, natively-compiled applications for mobile, web, and desktop from a single codebase.
Flutter 是谷歌推出的便携式 UI 工具包,可以跨平台的构建精美的、原生体验的 Mobile 、 Web 、 Desktop 应用。
Flutter 的发展历程
2017年 Google I/O 大会上, Google 首次推出了一款新的用于创建跨平台、高性能的移动应用框架 —— Flutter 。
2018年2月, Flutter 发布了第一个 Beta 版本。
2018年5月,在2018年 Google I/O 大会上, Beta3 版本发布。
2018年6月, Flutter 发布了首个预览版本,这意味着 Flutter 进入了正式版(1.0)发布前的最后阶段。
2018年12月,1.0版本发布。
哪些企业在用 Flutter ?
- 阿里巴巴(闲鱼)
- 美团( B 端)
- ……
Flutter的的优点与缺点
优点:
- 性能高:由于自绘引擎是直接调用系统 API 来绘制 UI ,所以性能和原生控件接近。
- 灵活,易维护:由于 UI 渲染不依赖原生控件,不会受原生布局系统的限制,这样布局系统会非常灵活;且不需要根据不同平台的控件单独维护一套组件库,所以代码容易维护。
- 开发体验好:由于组件库是同一套代码、同一个渲染引擎,所以在不同平台,组件显示外观可以做到高保真和高一致性。
缺点:
- 动态性不足:为了保证 UI 绘制性能,自绘 UI 系统一般都会采用 AOT 模式编译其发布包,所以应用发布后,不能像 Hybrid 和 React Native 那些使用 JavaScript ( JIT )作为开发语言的框架那样动态下发代码。
React Native 简介
这句话是 React Native 官网 对 React Native 的概述,简单明了地概括了 React Native 的特点和优点。
React Native 的发展历程
哪些企业在用 React Native ?
- 腾讯( QQ 空间、 QQ 音乐)
- 百度(手机百度)
- 京东
- ……
React Native 的优点与缺点
优点:
- 社区庞大、上手快、开发成本相对较低。
- 原生渲染,性能相比 H5 提高很多。
- 动态化较好,支持热更新。
缺点:
- 渲染时需要 JavaScript 和原生之间通信,某些场景下如拖动可能会因为通信频繁导致卡顿。
- JavaScript 为脚本语言,执行时需要 JIT ,执行效率和 AOT 代码仍有差距。
- 由于渲染依赖原生控件,不同平台的控件需要单独维护,并且当系统更新时,社区控件可能会滞后;除此之外,其控件系统也会受到原生 UI 系统限制。
React Native 和 Flutter 的对比
—— | React Native | Flutter | 相同点 | 结论 |
---|---|---|---|---|
环境搭建 | npm 、 node 、 react-native-cli 等 | Flutter SDK 和 Android Studio / VSCode 上的 Dart 与 Flutter 插件 | JDK 、 Android SDK 、 Xcode 等 | 首次配置运行成功率: Flutter > React Native |
实现原理 | React Native 是一套 UI 框架,默认情况下 React Native 会在 Activity 下加载 JavaScript 文件,然后运行在 JavaScriptCore 中解析 Bundle 文件布局,最终堆叠出一系列的原生控件进行渲染 | Flutter 中绝大部分的 Widget 都与平台无关, 开发者基于 Framework 开发 App ,而 Framework 运行在 Engine 之上,由 Engine 进行适配和跨平台支持。这个跨平台的支持过程,其实就是将 Flutter UI 中的 Widget “数据化”,然后通过 Engine 上的 Skia 直接绘制到屏幕上 | 在 Android 和 iOS 上,默认情况下 Flutter 和 React Native 都需要一个原生平台的 Activity / ViewController 支持,且在原生层面属于一个“单页面应用” | 平台关联性: React Native > Flutter UI |
编程开发(语言) | JavaScript 是动态语言 | Dart 是伪动态语言的强类型语言 | 支持通过 var 定义变量,支持 async / await 语法糖,支持 Promise ( Future ) 等链式异步处理 | 开发便捷度: JavaScript > Dart 类型安全和重构代码: Dart > JavaScript |
编程开发(界面开发) | 延续了 React 的开发风格,不同之处就是更换标签名,并且样式和属性支持因为平台兼容做了删减 | 一切皆为 Widget 。控件嵌套和样式代码不分离 | 平台相关性: React Native > Flutter | |
编程开发(状态管理) | 在 Component 内初始化一个 this.state 变量,然后通过 this.state.name 访问,内部实现受 React diff 等影响 | 继承 StatefulWidget ,然后在 State 对象内通过变量直接访问和 setState 触发更新,内部实现受 isRepaintBoundary 、 markNeedsBuild 等影响 | 调用 setState 更新,且操作不是立即生效的 | |
编程开发(原生控件) | 整个渲染过程都在原生层中完成,所以接入原生控件并不难 | Flutter 的整体渲染脱离了原生层,直接和 GPU 交互,导致无法直接接入原生控件 | 混合开发支持: React Native > Flutter | |
插件开发 | npm 插件。好处:可以使用丰富的 npm 插件生态,同时减少前端开发者的学习成本。坏处: npm 包依赖复杂。每个项目都有一个 node_modules ,占用空间(现在, yarn pnp 提供了一种更加高效的模块查找机制,消除了项目中的 node_modules ,所有的依赖包都在一个公共目录里面) | pub 插件。 packages get 文件一般保存在电脑的统一位置,多个项目都引用着同一份插件 | 支持插件开发 | 体验: Flutter > React Native |
编译产物 | 编译后的文件主要是 bundle 文件,在 Android 中是 index.android.bunlde 文件,而在 iOS 下是 main.jsbundle | 在 Android 主要是: isolate_snapshot_instr (应用程序指令段)、 isolate_snapshot_data (应用程序数据段)、 vm_snapshot_data (虚拟机数据段)、 vm_snapshot_instr (虚拟机指令段)等产物。在 iOS 主要是 App.framework ,其内部也包含了 kDartVmSnapshotData、kDartVmSnapshotInstructions、kDartIsolateSnapshotData、kDartIsolateSnapshotInstructions 四个部分 | ||
性能 | Dart 支持的 isolate ,属于完完全全的异步线程处理,可以通过 Port 快捷地进行异步交互,这大大拓展了 Flutter 在 Dart 层面的性能优势。 | JavaScript 和 Dart 都是单线程应用,利用了协程的概念实现异步效果 | 理论性能: Flutter > React Native | |
稳定性 | Github 上 open issue 只有700多(2020.06),整体上稳定性已经达到生产环境的要求,但由于对原生组件的依赖,随着 Android、iOS 的系统迭代,未来仍需要持续的完善稳定性和兼容性 | Github 上 open issue 达到7000+(2020.06),在稳定性方面还有很长的路要走 | 稳定性: React Native > Flutter | |
发展未来 | 在0.59版本开始支持 React Hook 等特性,并将原本平台的特性控件从 React Native 内部剥离到社区,这样控件的单独升级维护可以更加便捷,同时让 React Native 与 React 之间的界限越发模糊。但是由于平台关联性太强,这些年发展较为缓慢 | Flutter UI 的平台无关性,让 Flutter 在跨平台的拓展上更为迅速 |
如何选择 React Native 或 Flutter
选择 React Native,如果你希望
- 从前端工程师或 Web 开发者的视角接触跨平台开发
- 拥有完善的工具链和成熟的生态系统
- 缩短产品的发布周期
选择 Flutter,如果你希望
- 从原生开发者的视角接触跨平台开发
- 关注产品性能和开发体验(无需处理平台差异)
React Native 工作原理
使用 React Native 开发应用,我们通过 React 来构建应用。用 React 实现的组件会被 React 框架组织成“虚拟 DOM ”的形式,然后将“虚拟 DOM ”的渲染和交互映射到原生的视图上面。
React 执行渲染(组件的装载和卸载、样式变化)操作后, JavaScript 会通知到 Native 端进行原生视图的渲染,原生视图的用户交互事件触发后,会通知 JavaScript 端声明的回调。
React Native 在与原生框架通信中,采用了 JavaScriptCore 作为 JavaScript Virtual Machine ( JS VM ),中间通过 JSON 文件与 Bridge 进行通信。若使用 Chrome 浏览器进行调试,那么所有的 JavaScript 代码都将运行在 Chrome 的 V8 引擎中,与原生代码通过 WebSocket 进行通信。
一个 JS VM 实例代表一个执行 JavaScript 的自包含( self-contained )的环境。你可以用这个类做两件事情: ① JavaScript 的并发执行; ② 桥接 JavaScript 和 Objective-C 或 Swift 的对象的内存管理。
JavaScript 代码并不是被编译成 Native 代码,而是在各个平台的 JS VM 中被执行的。在 iOS 中, JS VM 是 iOS 系统提供的 JavaScriptCore ;而在 Android 中,是 React Native 这个框架提供的,打包进 APK 中的的某个版本的 JavaScriptCore (或者是 Facebook 的 Hermes 引擎)。
JavaScriptCore 主要功能是解析执行 JavaScript 脚本。它支持在原生环境( Objective-C 、 Swift 、 C )中执行 JavaScript 代码,同时支持把原生对象注入到 JavaScript 环境中使用,结合这两点 JavaScriptCore 就具备 JavaScript & Native 交互的能力。 React Native 正是利用它的这一特性,在 JavaScriptCore 的基础上构建一座桥梁( Bridge ),使得 Native 与 JavaScript 可以高效且便捷地互相调用,这便是 React Native 框架的核心。
React Native 部署调试
项目运行
iOS 平台:
- 使用 Xcode 打开 ios/.xcodeproj ,选择模拟器后点击运行按钮
react-native run-ios --simulator "iPhone 8"
xcrun simctl list devices
可以获取到 Xcode 下所有可用的设备列表
Android 平台:
执行react-native start
,打开 Android Studio
- 选择 Configure -> AVD Manager , 点击运行按钮
- 打开项目, 点击运行按钮
开发调试
- 开发者菜单( iOS : Command + D, Android : Command + M)
- Chrome + React Developer Tools
React Developer Tools :
安装:npm install -g react-devtools
运行:react-devtools
- React Native Debugger
安装:
brew update && brew cask install react-native-debugger
- 真机调试
以 Android 为例:
- 开启 USB 调试
- 使用
adb devices
命令可以检查设备是否正确连接到 ADB ( Android Debug Bridge ),右边那列看到 device 说明你的设备已经被正确连接了。
注意,你每次只应当连接一个设备。如果你连接了多个设备(包含模拟器在内),后续的一些操作可能会失败。
跨平台框架与React Native基础的更多相关文章
- React Native基础&入门教程:初步使用Flexbox布局
在上篇中,笔者分享了部分安装并调试React Native应用过程里的一点经验,如果还没有看过的同学请点击<React Native基础&入门教程:调试React Native应用的一小 ...
- react native基础与入门
react native基础与入门 一.react native 的优点 1.跨平台(一才两用) 2.低投入高回报 (开发成本低.代码复用率高) 3.性能高:拥有独立的js渲染引擎,比传统的h5+ w ...
- React Native基础&入门教程:调试React Native应用的一小步
React Native(以下简称RN)为传统前端开发者打开了一扇新的大门.其中,使用浏览器的调试工具去Debug移动端的代码,无疑是最吸引开发人员的特性之一. 试想一下,当你在手机屏幕按下一个按钮, ...
- 带你从零学ReactNative开发跨平台App开发[react native SqlLite 终极运用](十二)
ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...
- React Native基础概念和基础认识
学习地址:https://github.com/vczero/react-native-lesson 当我们初始化一个RN项目的时候主要的是index.ios.js文件和index.android.j ...
- React Native基础&入门教程:以一个To Do List小例子,看props和state
本文由葡萄城技术团队于博客园原创并首发 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 在上篇中,我们介绍了什么是Flexbox布局,以及如何使用Flexb ...
- 带你从零学ReactNative开发跨平台App开发-[react native 仿boss直聘](十三)
ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...
- React Native 基础报错及解决方案记录
刚开始上手RN,碰到很多坑,记录一下.碰到问题多去看看github上面的issue! 启动命令react-native run-ios报错 1.:xcrun: error: unable to fin ...
- 使用React Native来撰写跨平台的App
React Native 是一个 JavaScript 的框架,用来撰写实时的.可原生呈现 iOS 和 Android 的应用.其是基于 React的,而 React 是 Facebook 的用于构建 ...
随机推荐
- day2 变量
变量是在程序中表现为不重复的名字,只需定义一个名字,给这个名字变量赋值即可 作用 在内存中开辟一块空间.起了一个别名,用了访问和存储空间中的数据 在编写 Python 程序过程中, 经常需要给标识 ...
- 学习java的第五周
java流程控制 顺序结构 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执的处理步骤组成的,它是任何-一个算法都离不开的一种基本算法结构. 选择结构 if结构 if(布尔表达式 ...
- CSS动画实例:Loading加载动画效果(三)
3.小圆型Loading 这类Loading动画的基本思想是:在呈现容器中定义1个或多个子层,再对每个子层进行样式定义,使得其均显示为一个实心圆形,最后编写关键帧动画控制,使得各个实心圆或者大小发生改 ...
- JavaScript学习系列博客_35_JavaScript 正则表达式的使用
正则表达式的使用 先说RegExp对象的一个方法 test() - 使用这个方法可以用来检查一个字符串是否符合正则表达式的规则,如果符合则返回true,否则返回false. 1.用正则表达式来检查一个 ...
- 【翻译】Promises/A+规范
目录 介绍 译文 1. 术语(Terminology) 2. 要求(Requirements) 2.1 Promise状态 2.2 then方法 2.3 Promise解析程序 3. 注释 3.1 p ...
- oracle replace的用法
表数据里面有些数据是有换行或者特殊字符的,想要去掉,但是几千条记录要一条条改基本不可能. 后来想到了replace这个函数,具体用法如下: update 表1 t set t.列1=replace(( ...
- 数组的三种方式总结 多维数组的遍历 Arrays类的常用方法总结
一.数组的三种声明方式总结 public class WhatEver { public static void main(String[] args) { //第一种 例: String[] tes ...
- 区块链入门到实战(23)之以太坊(Ethereum) – 虚拟机架构
以太坊(Ethereum)网络中,定义了一组通用协议用于支持智能合约的运行,其核心便是以太坊(Ethereum)虚拟机. 下图解释了该架构: 开发人员使用Solidity等开发语言开发智能合约 源程序 ...
- SLS案例中心
今日PV nginx日志查看今日的PV和昨日的对比,先通过count函数计算总的pv,再用compare函数得出今日的pv和昨日的同比. 通过单值图进行展示,显示值为20.381Mil,对比值为-2% ...
- vue组件获取和vue-cli的基本了解
Vue获取组件的一些方法 this.$refs.xxx 给标签绑定ref属性,获取的是当前DOM对象 给组件绑定ref属性,获取的是组件实例对象 this.$parent 获取当前组件的父组件,为一个 ...