乐分享 加入收藏  -  设为首页
您的位置:生活百科网 > 知识百科 > 正文
如何评价 React Native
如何评价 React Native
提示:

如何评价 React Native

先说结论:必有作为,但绝不会是一家独大,甚至很难成为主流。

用过 React 会知道,React 的核心概念是「DOM Representation」,在开发者和 DOM 中间构建一个中间件,然后通过高效的算法来 diff 两次 Virtual DOM 渲染的差异,然后在最小范围内更新 DOM,在大部分情况下——注意是大部分不是所有——这种做法都是足够高效的,但是对于精细的需求、动画控制等——比如在移动设备上做一个跟随 touchmove 的元素,还要各种 transition 等等——场景 React 会显得力不从心,或者很笨拙。

但是抛开这些太过复杂的需求,React 是有能力满足大部分的业务场景的。

再说 React Native,这几天不停看见媒体用「Web 开发要 XXX」一类的题目来发稿,真是吐槽无力。React Native 根本都不算 Web 开发好不好——Webview 都没了还 Web 个 bird 啊...

React Native 继承了 React 在 JavaScript 的扩展语法 JSX 中直接以声明式的方式来描述 UI 结构的机制,并实现了一个 CSS 的子集,这把「DOM Representation」的概念外扩成了「UI Representation」,由于不是操作真实 UI,就可以放到非 UI 线程来进行 render——所有做客户端 UI 开发的都应该知道 UI 线程是永远的痛,无论你怎么 render,render 的多低效,这些 render 都不会直接影响 UI,而要借由 React Native 来将改变更新回 UI 线程。

由于目前没有任何示例代码,也看不到更细节的实现机制介绍,所以以下部分为猜测。如果 React Native 沿袭 React 的机制,就会同样是把两次 render 的 diff 结果算出来,然后把 diff 结果传递回主线程,在最小范围内更新 UI。

所以,核心是以下三点:
1. 在非 UI 线程渲染 UI Representation
2. 高效的 diff 算法保证 UI update 的高效
3. 没错,由于中间件的机制,React 很有可能成为一个跨平台的统一 UI 解决方案,可以理解为 UI 开发的虚拟机?

声明式 UI 开发,简单快捷,必然大有作为。精细控制无力,复杂应用场景无法很好满足,必然受限。

如何评价 React Native
提示:

如何评价 React Native

React native充分利用了Facebook的现有轮子,是一个很优秀的集成作品,并且我相信这个团队对前端的了解很深刻,否则不可能让Native code「退居二线」。


对应到前端开发,整个系统结构是这样:
JSX vs HTML
CSS-layout vs css
ECMAScript 6 vs ECMAScript 5
React native View vs DOM
无需编译,我在第一次编译了ipa装好以后,就再也没更新过app,只要更新云端的js代码,reload一下,整个界面就全变了。
多数布局代码都是JSX,所有Native组件都是标签化的,这对于前端程序员来说,降低了不少学习成本,也大大减少了代码量。不信你可以看看JSX编译后的代码。
复用React系统,也减少了一定学习和开发成本,更重要的是利用了React里面的分层和diff机制。js层传给Native层的是一个diff后的json,然后由Native将这个数据映射成真正的布局视图。
css-layout也是点睛之笔,前端可以继续用熟悉的类css方式来编写布局,通过这个工具转换成constrain布局。

统只有js-objc的单向调用,就是把原生UI组件的方法通过javascritcore或者webview(低版本iOS)映射到js中来,整个调用
过程是异步的,这样的设计令React native可以让js运行在桌面chrome中,通过websocket连接Native
code和桌面chrome,极大地方便了调试。对其中的机制Bang的一篇文章写得很详细,我就不拾人牙慧了:React Native通信机制详解 « bang’s blog 。但这样设计也会带来一些问题,后面说。
点按操作也被抽象成了一组组件(TouchableXXX),这种抽象方式是我在之前做类似工作中没有想到的。facebook还列出Native为什么和web「手感」不同的原因:实时的点按反馈和取消能力。React Native 这套相应机制设计得很完善,能像Native code那样控制整个点按操作的所有过程。

Debug
相当方便!修改了js以后,通过内建的nodejs
watcher编译成bundle,在模拟器里面按cmd+r就可以看到效果。而且按cmd+d,可以打开一个chrome窗口,所有的js都移到了
chrome里面运行,所以什么断点单步打调用栈,都不在话下。

上面的既是特点也是优点,下面说说缺点,或者应该说:「仍然遗留的问题」,在我看来,这个方案已经超越了Hybird方案。

统仍然(不得不)依赖原生组件暴露出来的组件和方法。举两个例子,ScrollView这个组件,在Native层是有大量事件
的,scrollViewWillBeginDragging,
scrollViewWillEndDragging,scrollViewDidEndDragging等等,这些事件在现有的版本都没有暴露,基本上
做不了组件联动效果。另外,这个版本中有大量组件是iOS
only的:ActivityIndicatorIOS、DatePickerIOS、NavigatorIOS、PickerIOS、
SliderIOS、SwitchIOS、TabBarIOS、AlertIOS、AppStateIOS、LinkingIOS、
PushNotificationIOS、StatusBarIOS、VibrationIOS,反过来看,剩余的都是一些抽象程度极强的基本组件。这
样,用户必须在不同的平台下写两套代码,而且所有能力仍然强烈依赖 React native 开发人员暴露的接口。
由于最外层是
React,初次学习成本高,不像往常的Hybird方案,只要多学几个JS
API就可以开始干活了。当然,React的确让后续开发变得简单了一些,这么一套外来的(基于iOS)、残缺不全的(css-layout)在
React的包装下,的确显得不那么面目可憎了。
另外,React Native仍然很不完善。文档还不全,我基本上是看着他的示例代码完成的demo,集成到已有app的文档也是今天才出来。按照官方的说法,Android版本要到半年后才发布:Blog | React ,届时整个系统设计可能还会有很大的变化。

PS,在使用Tabbar的时候,我惊喜的发现他们居然用了iconfont方案,我现在手头的项目中也有同样的实现,不过API怎么设计一直很头疼。结果,我发现他是这么写的:
<TabBarItemIOS
name="blueTab"
icon={_ix_DEPRECATED('favorites')}
....>


在 _ix_DEPRECATED 的定义处,有一句注释: // TODO(nicklockwood): How can this fit our require system?



以上。




下面是一周前,在React native还没开源的时候,通过反解ipa的一些分析过程,有兴趣的可以看看。


------------------------简单粗暴的分割线--------------------

背景和调研手段
React
Native还没开源,最近和组里兄弟「反编译」了Facebook Group(这个应用是用React
Native实现的)的ipa代码,出来几百个JS文件,格式化一下,花了几天时间读了一下源码,对React
Native的内部核心机制算是有了一个基本了解。

React Native的核心实现:

先简单说几点,详细的等回头更新。

1. React Native里面没有webview,这货不是Hybrid app,里面执行JS是用的
JavascriptCore。
2. 再说React Native的核心,iOS Native code提供了十来个最基本核心的类(RCTDeviceEventEmitter、
RCTRenderingPerf等)、或组件(RCTView、RCTTextField、RCTTextView、
RCTModalFullscreenView等),然后由React Native的JS部分,组成二十来个基本组件(Popover、Listview等),交由上层的业务方来使用(THGroupView)。
3. 就如他们在宣传时所说,他们实现了一套类似css的子集,用来解决样式问题,相当复杂和强大,靠这个才能将Native的核心组件组成JS层的基本组件再组成业务端的业务组件,应该是采用facebook/css-layout · GitHub的C语言版本实现的(在ppt中我们看到了类似flex-direction: column一类的代码,这个正是css-layout支持的语法)。
4. 在React Native中,写JS的工程师解决的是「将基本组件拼装成可用的React组件」的问题,写Native Code的工程师解决的是「提供核心组件,提供足够的扩展性、灵活性和性能」的问题。


React Native的设计考虑:

ReactJS对React Native有着直接的影响(我没在生产环境中用过React,只看过代码&用过Angular,如果有误请指出)

ReactJS里面有这样的设计:
1. ReactJS 的大工厂入口createElement返回的不是某个实体DOM对象,而只是一个数组
2. 通过源码中 ui/browser/ 目录中的代码,将这个数组转换成DOM
3. 底层的渲染核心是可以更换的

另外,Facebook自己有JSX,css-layout等开源项目,基于这些,如果要做一个用 JS来开发Native app的东西,很自然就想到了一套最有效率的搞法:

1. 将 ui/browser 里面的代码替换成一套 Native 的桥接JS(实际上,iOS版是通过
injectGenericComponentClass方法,将核心组件的方法注入到JS里面 ),就直接复用React的MVVM,自动将数据映射到Native了
2.
Native
code里面实现三组核心API,一组提供核心组件的API(create、update、delete),一组事件方法(ReactJS里面的
EventEmitter ),一组对css进行解析(css-layout)以及返回Style的ComputedStyle(React
Native里面叫meatureStyle)。

这样,用上了ReactJS本身的所有核心功能和设计思路,Native的开发也足够简单。


那,React Native是什么?

其实这东西从Native开发来说,相当于重新发明了一个浏览器渲染引擎并且套一个React的壳,从Web开发角度来说,就是把原来React的后端换成了Native code来实现,就跟Flipboard最近搞的React Canvas 一样: Flipboard · GitHubreact-canvas


React Native的优势和劣势::

优势相对Hybird app或者Webapp:
1. 不用Webview,彻底摆脱了Webview让人不爽的交互和性能问题
2. 有较强的扩展性,这是因为Native端提供的是基本控件,JS可以自由组合使用
3. 可以直接使用Native原生的「牛逼」动画(在FB Group这个app里面,面板滑出带一点果冻弹动,面板基于某个点展开这种动画随处可见,这种动画用Native code来做小菜一碟,但是用Web来做就难上加难)。

优势相对于Native app:
1. 可以通过更新远端JS,直接更新app,不过这快成为各家大型Native app的标配了…

劣势:
1. 扩展性仍然远远不如web,也远远不如直接写Native code(这个不用废话解释了吧)
2.

从Native到Web,要做很多概念转换,势必造成双方都要妥协。比如web要用一套CSS的阉割版,Native通过css-layout拿到最终样
式再转换成native原生的表达方式(比如iOS的Constraint\origin\Center等属性),再比如动画。另外,若Android和
iOS都要做相同的封装,概念转换就更复杂了。

更新1:添加了React对React Native的影响。
更新2:基本确定其使用了 css-layout,添加了对React Native的总结
更新3: React native已经开源了: React Native,只有iOS版。我写了几个demo,简单看了看objc代码并和开源前的我们的一些结论(见后文)交叉验证。简单地从前端工程师和系统整体角度说一下React native的特点和优劣吧。
更新4: 补充了几条优势和与前端开发的对照