如何看待 BrendanEich,Vjeux d eau等人就 React Native 的讨论

如何评价 React Native?
我的图书馆
如何评价 React Native?
优势:js 可以直接被 native 端执行,也可以和 native code 进行通讯,进而可以调用一些 native 提供的接口。 能直接被执行的好处在于可以直接从服务器上载入并执行 js 代码,这点在 iOS 上是 native code 和其他 to objc 的语言都难以做到的。这使我们有了一些更灵活的方法,来完成诸如应用内更新或者开发应用内插件之类的工作。同时,iOS 和 Android 可以共享一些前端部分的代码,使得代码能够更好地重用。
.zm-item-answer"}' data-widget="navigable" data-pagesize="20">
劣势:界面渲染效率低,多线程支持差,GC 问题。在 WebView 中绘制界面、实现动画的效率都比较低,开销也比较大。WebWorker 提供的多线程在 native 端有很大的局限,js 在 GC 时也有可能卡 UI。React Native 的做法非常激进,完全抛弃了 HTML(抛弃了 HTML 不代表抛弃了声明式),抛弃了 WebView,在 background thread 里运行 js 并直接使用原生控件进行渲染。这从根本上解决了渲染问题,使得 js 不再只能做 hybrid app,而能做出具有 native behavior 的流畅靠谱的 native app。从这一点上来说 React Native 已经做得相当不错了,尽管它只实现了 CSS 的子集,但是考虑到 CSS 如此复杂而它又抛弃了使用 webview 渲染,这是可以接受的。===========但是,React 的意义绝不在于解决了一些 hybrid app 的痛点。React 是一个很有野心的项目,它的目标不仅仅是简单地使前端能用 js 写 native app,而是希望推广一个通用的前端构建方案,不论是 Web 前端,还是客户端前端。FB 在演讲里说,React 的目标不是 “Write once, run anywhere",因为不同平台的差异是客观存在的,设计风格也各有不同。它要做的,是 “Learn once, write anywhere”。React 里的 view 不仅可以是 DOM,也可以是 iOS 控件或者 Android 控件,不论是什么平台,都能 “build in React”。就我看来,前端不只是需要写网页,更重要的是要解决属于前端领域的各种问题。Web 前端和客户端前端在本质上是一致的,探索前端领域的最佳实践是一件很有意义的事。近些年前端比较火,相比于自成体系较为封闭的客户端前端, Web 前端在前端实践上的探索或许更多一些。不管是阿里的 Midway 那样侵入到后端的 UI layer,还是像 React Native 这样侵入到客户端前端,我认为都是非常值得称赞的探索。至于到底怎么评价 React Native,我觉得它和 React 一样赞。===========最后附个 FB 关于 React Native 的演讲:
,我在学 CoffeeScript
、知乎用户、 等人赞同
一直在跟进 React.js , 中文论坛()也主要是我在维护, 吐个槽本人前端, Macbook 用户, Android 用户, 但是不会移动端的开发首先如果 Facebook 发布 React Native, 那么移动端开发的门槛瞬间降低, 非常好的消息当然这个也将促使更多人选择 React 这样一套方案, 社区当中的资源也会更丰富结果就是会有很多人来参与研究用 React 的范式怎样来编程, 这是我们非常希望看到的React 有一个观点很明白, 就是以往的编程太多过程式的写法, 他们想要变成声明式的,因为声明式的写法能讲底层逻辑交给可靠的代码, 那么开发者的门槛极大地降低发布会演讲提到的就是随着应用变大, 逻辑变复杂, 用 React 的话后来的开发者很好上手相信这也是很多人选择 Angular 的原因.. 虽然两者实现声明式编程的语法和方式差别还是不小那么 React 现在靠着它摆脱了 DOM 的高度的抽象, 想要把同样的开发方式复制到本地应用!顺带地, React 把前端的事件系统, Flexbox 布局, 打算复制到移动开发上这个对于前端开发者来说会是很好的消息, 特别是已经用 React 写了很多前端代码的对于移动端我希望是在 React Native 稳定版发布以后, 能被移动端开发者认可...就我个人来说, 我倾向于认为 Functional Reactive Programming 一路的图形开发前途更好比如 Elm, 比如 React, 对界面还有数据及逻辑都做了比较理论化的考虑..那我很期待各种图形开发当中能引入这个我认为非常高效的方案另外, Web 开发当中灵活的布局系统我也希望在我学习开发其他平台时能继续使用.
,wild developer,on road,alive
知乎用户、、 赞同
其实最应该期待的是ui以及编译环境的整合,这些已经有ionic做榜样,js to native也有Ti趟了几年雷。工程结构上比ionic的angular讨巧。看起来会牛的,但这些优势目前我串不起来,没法预期会是个什么东西。我多说一点,以我的观察,没ide火起来难。
,JS語言研究,原理探究,應用優化
、、 等人赞同
我先来答吧。从很久以前就警告了用HTML5来做App有多不靠谱,不过各种Cloud还是不断出现。说到底,HTML5做App的优势和劣势都是HTML本身,或者说是DOM,成也萧何败也萧何。归功于CSS这个神器,UI制作变得非常简单而强大。但是却因为DOM这个东西,每次操作都比Native View慢很多,内存开销也很大。========分割线========1. ReactJS在JS圈子里的口碑在不断爬升(虽然我没用过),组件模式的开发体验对Native App来说非常适合。2. React Native宣称抛弃了DOM,而是纯净的JS Binding。但我还在怀疑他们是打算先用HTML做一次转换,还是直接修改React的体验,适配Native View。如果是后者,相信会非常棒。3. 还需要看看他们用的JS引擎,还有针对Mobile App的优化,比如GC。4. 从我个人角度看,FB把JS Binding和View Binding这套东西开源出来,比React自身更有意义。-----------------------看了 的回答,继续说下。现在确实各方神仙都想用自己的玩具来做本来不属于他们的领域,比如iOS。作为一个长期从事JavaScript开发的人,现在因为需求,要做iOS的开发。可能会有很多人想,有很好的前端能力,用HTML5来做会适合。但我没有这样做,而是买了一本Swift的书,重新学习一门语言。PS: 个人不太喜欢OC的语法,Swift对我来说基本可以跳过语法学习。就如上面说的,我了解完全用HTML5做App的危险性:维护成本,可用性,性能等等。有时候,学习相关的东西比用不相关的东西更来的快,更何况Swift很友好。我想说的是,跟风、傍大款是阻碍程序员进步的品质。还有,别把糖果当成银弹了。
,前端码畜,INTJ,各种秒收FLAG
、知乎用户、 等人赞同
现在趋势都是声明式UI,React却“反其道而行之”,把UI深绑定到JS中去。然后又嫌编程创建控件的方式,对于UI的树状结构太麻烦了,于是搞出了个JSX。我就纳了闷了,他们团队究竟是对JS有多执念?诚然,以现在的前端生态来看,JS的群众基础的确是好。但是用React以后,要尽量保证与传统DOM的绝缘(下文例1)。从ReactJS的Virtual DOM,到React Native的“No DOM”(引号是因为这词不是官方的)。对JS群众而言是个新的挑战。(而且JSX真的是不怎么不好用啊)因为还没有看到第二天的视频,具体的一些实例代码和技术细节都看不到,但从现在的理解看,它仅仅是用了JS而已,跟前端技术已经没什么关系了,东西都要重新学。这方面我会继续关注后面的视频。然后另一方面,因为我不会做Native开发,不知道各种控件样式一般而言是用什么来定义的,但是如果React Native要搞一套“Native CSS”,这又是个学习成本,同时也是个无底天坑了。定义样式这方面,昨天的视频里没有看到,今天的视频发出来了之后我会再关注一下。小结:React Native除了JSX以外,已经和JS的发源地——WEB前端技术没太大关系了,东西都要重新学。它并不能提供一个用Web的技术和经验来开发NativeApp的方式,这一点与Ionic有本质区别。前端开发者想因此快速做出Native开发,也许做做小样还行,做出严肃的产品,我认为还有距离。
结论:我不认为这是一条给前端转Native的出路。----------------------上文例1一些UI控件,比如模态框,很常见的实现方式是把模态框从定义的节点里摘出来,塞进BODY里面,这样定位什么的非常好搞。氮素,这样做会破坏真实DOM与Virtual DOM之间的关联关系,ReactJS会罢工。例如SemanticUI中的modal组件,需要指定`detachable`才能让它不把元素剥离进BODY里去,SemanticUI的文档中说这样做会造成渲染获得更少硬件加速的优化。这还是人UI组件库设计的比较周到,如果是要捡着自己的组件库用,还不知道要踩多少坑。相比之下,Angular要友好一些,我们写的UI组件自己接管状态维护之后,只需要修改$scope,然后调用$apply,把状态维护交还给它的digest循环就行了。具体就不展开讨论了。
,只会画线条的前端
当你手中只有一把锤子的时候,任何东西在你眼里都是钉子
,颜文字输入法开发者,前端乱炖创始人,大…
、、知乎用户 等人赞同
瞎说两句:1. 为什么所有语言都想用来写ios?现在还有不能写ios的语言么?2. 看了新闻,感觉还是ionic的思路,可能会更向native渗入一步?用native渲染UI?不过感觉不太可能。3. ionic这种框架并非无用武之地,面向B端的大型移动端CRM管理系统,多人协作,N多操作业务集合,和后台数据极重的业务耦合,这种场景下,考察来考察去,ionic是最适合的,目前感觉没有其他非常成熟的能够应用到生产中的框架。性能方面也不是非常不堪,性能方面ionic做的优化还是不错的,虽然并非完美。4. React和angularjs,没有特别深入,不过我作为一个开发者,并不关心他们的实现有多取巧,性能有多棒,模式有多新颖。我最关心的一点,开发方不方便?是否足够简单?团队开发快速上手?目前没看到React的优势,可能是了解不够多,但是感觉angularjs足够了,也不想了解更多。
知乎用户,计算机研究生
看了那个keynote,我看到的是脸书说他们的js跑到了一个单独的线程里面,所以很流畅。从这个思路来说,应该是直接用native ui的程序员不会注意写多线程,而用了react native 天生并发加成?
HHVM有什么意义?
,I love software.
Titanium () 就是和 React Native 一样的逻辑,用 js 调用原生控件。这样很好,解决了界面体验问题。不过也有没解决的问题。他们无法代替原生的 API,很多效果,开源的控件,都要用原生的代码来实现。简单的 app 没什么问题。遇到复杂的 app,还是原生代码来的靠谱。
知乎用户,android
服务器端有js语言的node.js,现在客户端又有了个js的react native,前端js,正所谓learn once write anywhere。虽然各个平台的东西需要熟悉,最起码语言层面可以节省一些不必要的精力。
馆藏&23162
TA的最新馆藏
喜欢该文的人也喜欢如何看待: qq空间Android团队,应用ReactNative技术到其app上? - 知乎7被浏览977分享邀请回答0添加评论分享收藏感谢收起如何评价 React Native? - 知乎7931被浏览1123955分享邀请回答Div.io: ,最近我们也会持续分析他,并且也在Android上做类似的实现,观点会迭代,文章会更新。- - - - - - React native充分利用了Facebook的现有轮子,是一个很优秀的集成作品,并且我相信这个团队对前端的了解很深刻,否则不可能让Native code「退居二线」。对应到前端开发,整个系统结构是这样:JSX vs HTMLCSS-layout vs cssECMAScript 6 vs ECMAScript 5React native View vs DOM无需编译,我在第一次编译了ipa装好以后,就再也没更新过app,只要更新云端的js代码,reload一下,整个界面就全变了。多数布局代码都是,所有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的一篇文章写得很详细,我就不拾人牙慧了: 。但这样设计也会带来一些问题,后面说。点按操作也被抽象成了一组组件(TouchableXXX),这种抽象方式是我在之前做类似工作中没有想到的。facebook还列出Native为什么和web「手感」不同的原因:实时的点按反馈和取消能力。 这套相应机制设计得很完善,能像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版本要到半年后才发布: ,届时整个系统设计可能还会有很大的变化。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层的基本组件再组成业务端的业务组件,应该是采用的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/ 目录中的代码,将这个数组转换成DOM3. 底层的渲染核心是可以更换的另外,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 一样: react-canvasReact 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已经开源了: ,只有iOS版。我写了几个demo,简单看了看objc代码并和开源前的我们的一些结论(见后文)交叉验证。简单地从前端工程师和系统整体角度说一下React native的特点和优劣吧。更新4: 补充了几条优势和与前端开发的对照54835 条评论分享收藏感谢收起/facebook/react-native/issues。1. Cache:我们现在项目中的图片缓存完全是自己借助[Redux-Persist]()实现的(主要是为了能够离线查看),但是这种Cache除了一些性能问题外,本身与iOS的URL Loading System是没有关系的。比如说,正常情况下,如果图片是在WebView打开查看的,你想再取出来,你只要不做任何特殊设置,你就可以通过NSURLCache取出来,像这样:NSURLCache *cache = [NSURLCache sharedURLCache];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSData *imgData = [cache cachedResponseForRequest:request].data;
UIImage *image = [UIImage imageWithData:imgData];
但是你会发现,在RN下URL Cache是取不出来的(至少我在40之前是这样的,现在由于使用我们自己造的缓存,在新版本中这个情况没有验证),那你需要创建一个NSURLProtocol的子类,自己实现利用NSURLCache缓存:#import "HttpProtocol.h"
@interface HttpProtocol ()
NSURLSessionDelegate,
NSURLSessionDataDelegate
@property(copy, nonatomic) NSURLSession*
@property(strong, nonatomic)NSURLSessionDataTask*
@implementation HttpProtocol
+ (void)start {
[NSURLProtocol registerClass:self];
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
if (request
&& ([request.URL.scheme isEqualToString:@"http"] || [request.URL.scheme isEqualToString:@"https"])
&& ([request.URL.pathExtension isEqualToString:@"jpg"] || [request.URL.pathExtension isEqualToString:@"png"] || [request.URL.pathExtension isEqualToString:@"bmp"] || [request.URL.pathExtension isEqualToString:@"gif"] ||
[request.URL.pathExtension isEqualToString:@"tiff"]|| [request.URL.pathExtension isEqualToString:@"jpeg"]||
[request.URL.pathExtension isEqualToString:@"JPEG"])) {
return YES;
return NO;
-(NSURLSession *)session {
if (!_session) {
NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.requestCachePolicy = NSURLRequestUseProtocolCacheP
_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue new]];
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id &NSURLProtocolClient&)client {
return [super initWithRequest:request cachedResponse:cachedResponse client:client];
- (void)startLoading {
NSURLCache* cache = [NSURLCache sharedURLCache];
NSCachedURLResponse* cachedResponse = [cache cachedResponseForRequest:self.request];
if (cachedResponse) {//有缓存,从缓存中加载...
NSData* data= cachedResponse.
NSString* mimeType = cachedResponse.response.MIMET
NSString* encoding = cachedResponse.response.textEncodingN
NSURLResponse* response = [[NSURLResponse alloc]initWithURL:self.request.URL MIMEType:mimeType expectedContentLength:data.length textEncodingName:encoding];
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[self.client URLProtocol:self didLoadData:data];
[self.client URLProtocolDidFinishLoading:self];
NSMutableURLRequest* newRequest = [self.request mutableCopy];
newRequest.cachePolicy = NSURLRequestUseProtocolCacheP
self.task = [self.session dataTaskWithRequest:newRequest];
[self.task resume];
-(void)stopLoading {
[self.task cancel];
self.task =
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
completionHandler(NSURLSessionResponseAllow);
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
[self.client URLProtocol:self didLoadData:data];
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
willCacheResponse:(NSCachedURLResponse *)proposedResponse
completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler{
completionHandler(proposedResponse);
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
if (error) {
[self.client URLProtocol:self didFailWithError:error];
[self.client URLProtocolDidFinishLoading:self];
实际上,我认为这样做缓存更加好,但是没有时间改……2. WebView:讲真,现在不用Webview的客户端真的似乎好像是不存在,但是RN自身的UIWebview由于添加了一些员原来UIWebview不具备的能力,比如postMessage(WKWebview里面的messagehandler),但是RN源码本身hack实现是有一些问题的:if (_messagingEnabled) {
#if RCT_DEV
// See isNative in lodash
NSString *testPostMessageNative = @"String(window.postMessage) === String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage')";
BOOL postMessageIsNative = [
[webView stringByEvaluatingJavaScriptFromString:testPostMessageNative]
isEqualToString:@"true"
if (!postMessageIsNative) {
RCTLogError(@"Setting onMessage on a WebView overrides existing values of window.postMessage, but a previous value was defined");
NSString *source = [NSString stringWithFormat:
@"window.originalPostMessage = window.postM"
"window.postMessage = function(data) {"
"window.location = '%@://%@?' + encodeURIComponent(String(data));"
"};", RCTJSNavigationScheme, RCTJSPostMessageHost
[webView stringByEvaluatingJavaScriptFromString:source];
可以看见,window对象的postMessage对象本身被hack掉了,如果你的页面逻辑又重写了postMessage方法,就会有问题。同样的,向页面发消息是通过webviewRef提供的postMessage方法(尽管在文档中没有提及),源码实现是这样的:- (void)postMessage:(NSString *)message
NSDictionary *eventInitDict = @{
@"data": message,
NSString *source = [NSString
stringWithFormat:@"document.dispatchEvent(new MessageEvent('message', %@));",
RCTJSONStringify(eventInitDict, NULL)
[_webView stringByEvaluatingJavaScriptFromString:source];
如果客户端想向发消息,你可能发现无法通信,这时你可以试试直接调用window.dispatchEvent(今天我就遇到了,在Safari连接到真机网页,并通过终端打印,document.dispatchEvent === window.dispatchEvent 的结果为true,但是前者无法通信,后者可以)3. DEBUG:详细有很多人跟我一样使用Webstorm进行调试,在最新版本中,你可以选择通过Node还是Chrome进行debug:我选择使用Chrome调试主要是因为官方[Devtool]()的原因。虽然工具很强大,但是你需要慎用,尤其是你想试试计时器是否起作用的时候:4.动画:RN的动画真的很难用,至少我是这么认为的。在看完腾讯Alloy Team相关技术文章后,做动画还是很别扭,这种别扭感超过了我在搞Mac开发时做动画的感觉。使用LayoutAnimation可能还能好一些,但是能做的实现是在有限,更不用说原生那种转场动画,做跨组件之间的动画更加蛋疼。然而这不是关键,如果你如果没有正确的使用动画,会对你业务代码的执行造成影响。比如说我们都知道使用InteractionManager.runAfterInteractions来跑耗时操作,然而里面代码的执行是依赖动画执行情况的,已经有很多人提出类似的issue了,比如这个:一些针对动画性能的优化上,比如你想对listview的cell的动画做一下深度定制,一些国外的实践经验也是要针对平台优化(也就是写原生的package),而不是琢磨RN的Animation:5.手势:这大概是另一个RN做的比较屎的地方,由于安卓和iOS在手势响应上有很大的差异,RN干脆自己搞了一套,但是并不很好。比如说你想在一个View上加一个双指触控的手势,大概需要一个这样的实现:this._panResponder = PanResponder.create({
// 要求成为响应者:
onStartShouldSetPanResponder: (evt, gestureState) =& {
return gestureState.numberActiveTouches === 2
onStartShouldSetPanResponderCapture: (evt, gestureState) =& {
return gestureState.numberActiveTouches === 2
onMoveShouldSetPanResponder: (evt, gestureState) =& false,
onMoveShouldSetPanResponderCapture: (evt, gestureState) =& false,
onPanResponderMove: (evt, gestureState) =& {
// 最近一次的移动距离为gestureState.move{X,Y}
if (gestureState.numberActiveTouches === 2) {
this.method()
// 从成为响应者开始时的累计手势移动距离为gestureState.d{x,y}
onPanResponderTerminationRequest: (evt, gestureState) =& true,
onPanResponderRelease: (evt, gestureState) =& {
// 用户放开了所有的触摸点,且此时视图已经成为了响应者。
// 一般来说这意味着一个手势操作已经成功完成。
onPanResponderTerminate: (evt, gestureState) =& {
// 另一个组件已经成为了新的响应者,所以当前手势将被取消。
onShouldBlockNativeResponder: (evt, gestureState) =& {
// 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
// 默认返回true。目前暂时只支持android。
return true;
但是如果你添加的视图如果是WebView,由于WebView本事也有一套手势系统,导致你添加的这个不起作用,我的解决方法是干脆自己添加一个原生手势,然后同过DeviceEmitter通知RN,像这样:#import "RootViewController.h"
#import "RCTBundleURLProvider.h"
#import "RCTRootView.h"
@interface RootViewController ()&UIGestureRecognizerDelegate&
@implementation RootViewController
- (instancetype)initWithApplication: (UIApplication*)application andLaunchOptions: (NSDictionary*)launchOptions {
if (self = [super init]) {
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"mockingbot"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTap:)];
tap.numberOfTouchesRequired = 2;
tap.delegate = self;
tap.delaysTouchesBegan = true;
[rootView addGestureRecognizer:tap];
self.view = rootView;
return self;
//需要设置于WebView自带手势共存
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
- (void)handleTap:(UITapGestureRecognizer*) tap {
[[NSNotificationCenter defaultCenter] postNotificationName:TapGesture object: nil];
手势Package:#import "RootResponManager.h"
#import "RootViewController.h"
@implementation RootResponManager
bool hasListeners;
RCT_EXPORT_MODULE();
- (NSArray&NSString *& *)supportedEvents {
return @[TapGesture];
// 在添加第一个监听函数时触发
-(void)startObserving {
hasListeners = YES;
// Set up any upstream listeners or background tasks as necessary
[NSNotificationCenter.defaultCenter addObserver:self
selector:@selector(sendTapGestureNotification:)
name:TapGesture
object:nil];
// Will be called when this module's last listener is removed, or on dealloc.
-(void)stopObserving {
hasListeners = NO;
// Remove upstream listeners, stop unnecessary background tasks
[NSNotificationCenter.defaultCenter removeObserver:self];
-(void)sendTapGestureNotification:(NSNotification*)notification {
if (hasListeners) {
[self sendEventWithName:TapGesture body:nil];
期初发现安卓和iOS在响应链上存在差异,最早的panResponder在安卓上是可用的,后来发现也需要原生手势比较好:public class MainActivity extends ReactActivity {
private GestureDetector detector;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
detector = new GestureDetector(this, new GestureHandler());
//这里的事件似乎是被子控件消费掉了,看看以后能不能想办法覆盖掉,目前以下代码不起任何作用
public boolean onTouchEvent(MotionEvent event) {
detector.onTouchEvent(event);
return super.onTouchEvent(event);
//控制触控事件分发的时机
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getPointerCount() == 2) {
sendBroadcast();
return super.dispatchTouchEvent(ev);
private final String NORMAL_ACTION = "TapGesture";
public void sendBroadcast() {
Intent intent = new Intent(NORMAL_ACTION);
getApplicationContext().sendBroadcast(intent);
class GestureHandler extends GestureDetector.SimpleOnGestureListener {
private String getActionName(int action) {
String name = "";
switch (action) {
case MotionEvent.ACTION_DOWN: {
name = "ACTION_DOWN";
case MotionEvent.ACTION_MOVE: {
name = "ACTION_MOVE";
case MotionEvent.ACTION_UP: {
name = "ACTION_UP";
return name;
总而言之,RN的手势蛋疼无比,如果有特殊需求,请先考虑使用原生手势。6. Text:要承认的是,es6的字符串模板的确很方便,Swift要等到4才有,OC用点语法糖才能做个差不多,像这样:NSString* str = @"AAAAA"
但是一谈到富文本,RN的&Text&嵌套简直是灾难(但是官方不这么认为),我顿时怀念YYText了。TextInput组件也有问题,主要是在中文输入法情况下,你如果输入一些字符串没有点击回车,而是单纯的让Input失去焦点,候选的输入内容不会被输入,类似的反应有很多,像这个:不过也有好消息,官方有望在0.47版本里面修复这个Bug:7. NPM:1)NPM与Cocoapods、Gradle、Maven相比,似乎Bug多了那么一些,在升级到5.X版本时,终于增加了package-lock.json,但是会导致你修改package.json来install失效,这时候请试着删掉package-lock.json再试试。2)RN升级也是一种痛苦,经历过0.39 -& 0.40升级的诸位相信一定也有类似的体会。3)只要你依赖的项目涉及跨平台的一些特性,或者用到了node-gyp,那么有很高几率在不同平台编译不通过,多数情况是在Mac可以通过,在Windows上却不行。在使用Realm、LeanCloud等SDK时都遇到过这种情况。4)由于RN迭代速度很快,一些不经常更新的三方库可能干脆就跑不了了(虽然Swift的一些三方库也有这个问题,但是Swift迭代速度没有RN那么丧病),我现在仍然可以看到有些公司的iOS客户端仍然在用已经很久没有维护的ASI,但是没有见过有人用RN 0.2x版本时的package。8. CI:把一个平台的CI从写脚本到跑通对我来说大概需要一到两天的时间,然而你需要跑三个平台。额,应该不是乘以三倍的时间……如果你做的是个开源的RN项目,用Travis做CI,可以看看这篇文章,然后自己试着搞一下,大概就能体会RN CI的痛苦:目前就想到这些,欢迎大家补充。如果你们看了以后,仍然觉得解决RN的Bug很快乐(你们真的很有开源精神),可以再试试把项目完全切换到RN,否则,还是考虑一下原生+RN的方式吧。11821 条评论分享收藏感谢收起查看更多回答16 个回答被折叠()

我要回帖

更多关于 jeux 的文章

 

随机推荐