我已经做过一大堆 iOS 应用 — 其中有我为之骄傲的优秀应用。那些在 Xcode 中构建的应用都是使用 Objective-C 编写的,因为那是它一直就有的方法。那是苹果公司提供给我们来制作 iOS 应用的,因此我以及其它的开发者都会用到。之后,两年以前当苹果公司发布了 Swift 编程语言,我毫不犹豫的去尝试了一下。
那仍然可以使用 xcode,并且(很明显地)它仍然可以很顺利地开发 iOS 应用程序,我可以很直接地把它拾起来--啊哟--快一点,我愿意一直使用我的苹果生态系统。react native 仿佛对我来说是一个有趣的小实验,然而在我的脑海里,任何真实的本地的应用仍需要写这个本地的方法。那仿佛对我来说要浪费时间,不仅要学习 JavaScript(我毫无经验)而且要建立一个完整的新的应用程序方法,当我已经开始掌握建立他们“真实”的方法时。
如果时间快进一两个月,我可以很自信地说,我可能从来也不会使用
Objective-C 或者 swift 来写 iOS 应用。
我们收到了一个新的移动应用项目,并且我回顾了此需求和设计方案。正当我要敲击那个美丽的 xcode 蓝色图标,开始启动一个新项目时,我们的互动总监 Adam,走过来,说:“让我们使用 React Native 来做到这一点”。
他解释道这个项目合同的一部分明确要求这个 app 也得可用于 Android。尽管 React Native 不曾(现在也不)可用于 Android,但是我们知道 Facebook 活跃在这点上。理论上,如果我们用 iOS 版的 React Native 构建 app,很多部分可以在 Android 版发布后“立刻工作”。
好吧,我不是太开心。我觉得我站在 iOS 开发能力的顶峰,但却被要求完全不用这能力。我怀疑自己是否有能力在不可避免的学习曲线中按时交付质量可靠的产品。更糟的是,我怀疑 React Native 本身是否有能力产出一个质量可靠的产品。回头看看,我甚至不觉得这怀疑是不公的。那时React Native 才刚刚在 beta 阶段。文档缺失,开源 React Native 库和组件极少,而且供参考的代码示例或者 Stack Overflow 帖子几乎没有。
我不大愿意地开始尝试它。但是我闭塞的态度造成了更多的负面影响。我的第一道槛是学习 React Native处理 UI 布局的方式 Flexbox。从界面构造器转变成完全用代码设计 UI 几乎毁了我的三观。我痛苦地构建着最简单的视图。
但不仅仅是UI——所有的事都不一样了。
那是我最大的论点。
每次我卡住或者不明白某些东西,我总是告诉我自己“用 Objective-C 的话我5秒钟就能搞定”。每次我发现 ReactNative 的一个 bug 时(数量可观),我总想“这 bug 在 Object-C 里就不存在,为什么我要在这儿跟它斗个你死我活?”。
整整两个星期,我的工作悲惨万分。我感觉从一个专家级的 iOS 开发者变成了一个这辈子没写过一行代码的傻子。我要崩溃了,直到我花了一个周末清理我的脑袋。我往回走了一步,发现 Adam 早已做了很多 React Native 的研究。我必须相信他作为我们的交互总监不会把我带入一条烂路。我决定周一好好干,把脑袋冷静下来,假装 Object-C 和 Swift 从来没存在过,然后把这事儿搞定。
学习爱上React
几周前,我们提交了我们的第一个 React Native 应用到 App Store。我为这 app 的表现感到极其自豪,我迫不及待地要写下一个了。考虑到我仅仅一个多月前才完全搭上 React Native 这辆车,是什么改变了我的想法呢?
React 范式
在 React 中,每一份 UI 正在或者将一直存活于 render() 方法中,并且通过“状态”控制。render() 方法定义了 UI 对应于每个状态的样子,并且通过调用 setState(),React 决定哪些需要改变并切实为你改变它。想象一个简单的视图,只有一个“Hello World”标签和一个按钮。每次点击按钮需要将标签在“Hello World”与“Goodbye World”之间切换。在 Objective-C 中,我需要在按钮的处理方法中写一些丑陋的if语句,像
if ([label.text isEqual:@”Hello World”]) {
label.text = @”Goodbye World”;
} else {
label.text = @”Hello World”;
}
它运行的挺好,但是那些UI代码完全与我之前创建标签的地方脱节了(可以在代码中或者在界面构建器中)。在 React 中,我们可以在我们的状态中定义一个 buttonClicked 的 bool 变量,那么 render() 方法中的标签就看起来是这样:
<Text>
{this.state.buttonClicked ? ‘Hello World’ : ‘Goodbye World’}</Text>
然后我们的按钮处理方法就变成这么简洁:
this.setState({buttonClicked: !this.state.buttonClicked});
所有的视图代码处在同一个地方,通过状态控制一切。这使得理解和调试代码变得前所未有的简单。
Flexbox
这是我起初最恨之入骨的 UI 布局工具,不过现在是我最喜欢的 React Native 的一部分了。我承认一开始很难领会它,但只要你一旦弄懂它,那么构建适应各种尺寸的屏幕的 UI 就会变得十分简单快速。我先前一直沉迷于 Xcode 的可视化界面构建器。现在看来,自动布局要比 Flexbox 复杂得多了。Flexbox 使用的类 CSS 的样式化方式使得样式重用只需要简单的复制粘贴。还有最棒的是,你可以不花多少时间就将样式调至完美。
实时的重新载入
没错,要查看一个按钮向右移动 5 个像素的效果,不过是 Command+S 的事情。React Native 可以配置成在 iPhone 模拟器中自动重新渲染当前的视图,而不用重建 Xcode 项目。这是大有益处的,不仅因为省去了重建的时间,而且你可以处理嵌得很深的视图,并且调整 UI 时不用一路返回到上层的视图去。
Android
暂时还没,但就要来了——而且一定会很棒。我一开始对 React Native 犹豫不决是因为我早已喜欢上原生 iOS 开发。对此我没任何不满。但是我也做原生 Android 的开发,这就不大好了。React Native将会在 Android 圈很受欢迎,我扳着手指头等待这一刻来临。这将是移动应用开发的一场革命,一份代码两个平台。
怀旧情绪
想念 Xcode
我依旧想念 Xcode,或真的只是一个通常的 IDE。我努力搭建一个不错的 React Native 开发环境,但这没那么容易。Sublime Tex t加上一堆插件提供了我不错的代码高亮和检查。Sbulime 能基于同一个文件中的其它变量等提供代码自动完成功能,但是没有 Xcode 那么健壮好用。我依旧需要全程开着 React 的文档作为参考。
像是键入 React.PropTypes.f 后 IDE 没提示‘func’或者‘function’,这种小事是挺讨厌的。我还想念 Xcode 的版本编辑器,它可以允许我细致地与上一个 git 提交中的文件作比较,甚至还可以在行的级别上进行撤销改动。我知道第三方程序可以做到这点,但作为 IDE 的一个重要特征就是包办所有啊。
要运行一个 React Native 项目,我需要运行终端来启动 npm 打包,运行 Chrome 来调试,运行 Sublime 来改代码,最后运行 Xcode 来开始项目以及模拟器。这些都瑕不掩瑜,但的确是阻碍我迈向 React Native 的负面因素。我强烈希望 Nuclide(Facebook 的 IDE)可以解决部分或全部的这些负面因素。
桥接(bridging)
Facebook 还没有或者说未来也并不打算将 iOS 的所有 API 都移植到 React Native 中,对剩余的部分他们提供了一种“桥接”的方式将事情交给 JavaScript 来做。我还要强调一次,当我第一次使用 React Native,关于 bridge 的文档简直糟透了。这种感觉让我在每一次使用 bridge 时,都会产生放弃 React Native 的冲动。但是在 Facebook 详细解释了 bridging 的过程,并提供更好的范例以后,它不再可怕。虽然仍然有些麻烦,但是可预见地将来种类繁多的 bridge 将会被开源,并可以在 npm 上获得。我会说,大部分 iOS API 已经可以了吗?
Bugs,文档和开源社区
如果你现在开始学习,我的抱怨的绝大多数已经不存在了。Bug 每天都被修复,发行版大概一个星期左右就会更新。文档仍需改进,但是已经有了巨大的提升。Facebook 和开源社区始终如一的对这个框架进行开发。参与 React Native 在 GitHub 上的讨论和在 Stack Overflow 上提问题对 React Native 来说是件好事。如果你是个 iOS 开发者,并且正在考虑是否使用 React Native,我要告诉你:”你不是一个人“。React Native 很棒,你或许应该试着以开放心态去拥抱她。还有就是不要把自己放到一个舒适的小隔间内,一如从前的我。
文章评论