翻译 | 从 ReactJS 到 React-Native—两者的主要差异是什么

6,503 阅读9分钟


华翔,Web前端开发工程师

著作权归作者所有,转载请联系作者获得授权。





React-Native已经诞生有两年左右了,自从适配了Android平台,能构建跨平台移动App开始,这套框架变得更有意思了。一些contributors甚至将其适配到Mac和Windows平台,听起来非常酷。

React-Native跟ReactJS非常相似,但是在开始尝试你第一个native app之前,也需要了解两者之间的一些差异。作为一个正在学习使用React-Native,并已经用它尝试构建过几个原生app的ReactJS web开发者,我将在本文给大家介绍我发现的二者之间的一些区别。

安装和打包

React-Native是一个框架,而ReactJS是用来构建站点的JavaScript库。当你用ReactJS开始一个新的项目,你或许需要选择一个类似Webpack的打包器,然后去指定你工程中所需要的打包模块。React-Native包含了你需要的所有东西,你几乎不再需要其他东西了。当你开始一个新项目,你会发现一切都很简单——你可以只需要在命令行敲一行命令就行了——然后你就可使用ES6, 某些ES7特性,甚至一些比较新的polyfills开始你的编码。

你需要安装Xcode (在iOS和Mac平台)或Android Studio(在Android平台)来运行你的app。你也可以选择将你的app运行在你想使用的平台的模拟器(simulator/emulator)上,也可以直接运行在你自己设备上。

DOM和Styles

React-Native不使用HTML来渲染App,但是提供了可代替它的类似组件。这些React-Native组件映射到渲染到App中的真正的原生iOS和Android UI组件。

大多数组件都类似HTML,例如View组件跟div标签就很类似, Text组件类似于p标签。

import React, { Component } from 'react';
import { View, Text } from 'react-native';

export default class App extends Component {   render() {     return (       <View style={styles.container}>         <Text style={styles.intro}>Hello world!</Text>       </View>     );   } }


因为你的代码不是渲染在HTML页面中,这意味着你不能重用之前使用ReactJS渲染的HTMLSVGCanvas任何库。不过你能找到一些可代替的React-Native库。 react.parts的Native分类下或许可以找到你想要的东西。

为了给React-Native组件加上样式,你需要在JavaScript中添加样式表。这种样式表看起来像CSS,但实际上不太一样。在刚使用的时候会比较容易混淆,你或许想知道如何像你在SASS中那样创建mixins,或者你想重写一些可重用的组件。然而你会发现React-Native并不是为web元素而生,所以也不能这样使用styles。幸运的是,你或许能找到一些可代替的方案来满足你的需要。


尽管Flexbox已经诞生有很长一段时间了,但是我还是没有大量的使用它,我不知道你是怎样的,主要是因为我的项目中需要在一些老旧浏览器中有比较好兼容性。对于React-Native,使用Flexbox构建响应式App是最好不过的选择了。虽然它跟CSS中的表现不太一致,但是你理解之后你会觉得很方便。我推荐你阅读这篇文章来学习它: Understanding React Native flexbox layout。



const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    content: {
        backgroundColor: '#fff',
        padding: 30,
    },
    button: {
        alignSelf: 'center',
        marginTop: 20,
        width: 100,
    },
});


动画和手势

再见吧CSS动画!在React-Native中你需要通过JavsScript以一种全新的方式让不同的组件动起来。推荐的方式是使用React-Native提供的Animated API。可以类比于著名的JavaScript库Velocity.js。你可以通过它制作定时的或者基于手势的动画,也能跟不同的Easing(缓动)结合使用。所以你可以做出各种你在web中实现的效果。React-Native也提供了LayoutAnimation这种十分简单友好实现渐变的API,不过目前只适配了iOS平台,Android平台支持的不是很好。


为了跟用户手势很好的交互,React-Native提供了类似JavaScript的touch事件 web API,叫做PanResponder。安装和使用后或许会感到有些麻烦,但是你最终会发现其实它并不复杂。PanResponder能用到组件中的View (或者Text、Image)上以启用这个View组件的触摸事件。PanResponder提供了一系列function来捕捉用户的触摸事件,例如onPanResponderGrant  (touchstart ), onPanResponderMove (touchmove ) 或onPanResponderRelease  (touchend )。通过这些function可以得到原生事件和手势状态信息,如所有的touch、位置以及滑动距离,速度和触摸中心等。



使用PanResponder的react-native-swipeout组件

在我看来,使用PanResponder最大的问题是当你用PanResponder嵌套views/components的时候,你需要决定哪一个是受手势控制的。想了解更多关于动画和PanResponder,React-native Animated API with PanResponder 这篇文章将会非常有用。


导航

当我构建第一个React-Native App的时候,我很想知道怎样在两个界面之间导航。我最开始做的是去搜索react-router的代替品,大多数React App使用这个著名的库来实现页面迁移。我发现一些类似功能的库,但我发现总有一些东西我不太喜欢:有的使用起来十分复杂,有的我对它的动画不太满意,有的并不是我想要的自定义的方式,或者在iOS和Android平台表现不一致或不兼容。然后我很好奇导航到底是怎么实现的,我发现了React-Native提供的Navigator组件。我其实应该从这里开始的,找react-router的代替品并不是最好的选择。



通过Navigator在不同页面迁移

大多数的移动App不会像web App那样有大量的不同方向的页面迁移,尽管Navigator组件看起来会觉得复杂,因为他提供了管理页面迁移所需要的所有东西。我认为你应该坚持使用Navigator组件,除非你开发了一个规模庞大的移动App,需要很多的页面,或者你害怕在某些时候会混乱。你也可以看下NavigatorExperimental 这个组件,但在我看来,它还不适用于生成环境。


平台特殊代码

设计一套代码适配多平台的App有时候很方便,但是不久你的代码就会看起来很混乱。我可以肯定在现代浏览器里面写代码,并且想让其看起来在老旧浏览器里面“很美好”的时候也会有这种感受,得在CSS和JavaScript中到处加一系列的判断条件。

当你构建了一个原生App的时候,了解iOS和Android用户界面和体验的不同是很重要的,下面这篇文章解释的很好:Designing for both Android and iOS。

假定你可以控制App的界面和表现,你有两种选择:

  • 你可以为你的app在不同平台定义通用的设计,只要简单直观,并且不让不同平台的用户迷惑

  • 你可以为不同的平台写不同的代码,意味着你有不同的DOM、样式甚至不同的逻辑和动画,为了遵循不同平台的设计规范

如果你选择第二种方案,React-Native会检测运行的平台并加载平台对应的代码。推荐你将主要逻辑放到index.js这个组件中,这样你可以将展示组件放到单独的文件中。对于iOS和Android,各自也有 index.ios.jsindex.android.js这样单独的入口。

如果你按我的建议组织你的文件结构,大致是这样的:



/src
  /components 
    /Button
      /components
        /Icon
          /index.android.js
          /index.ios.js      
        /Content
          /index.android.js
          /index.ios.js
      /index.js


如果你觉得两个不同文件差异很小,也可以通过Platform模块来写条件判断。

开发者工具

当你开启一个新的项目,你几乎不需要安装任何东西就有一些React工具可以使用,这在我看起来很方便。 在你改动很少样式的时候Hot Reloading非常有用。对于App中较大的逻辑改动,修改代码的时候我一般使用Live Reload来重新加载整个App。

React-Native 调试工具

用React-Native最好的是,你在ReactJS中使用的开发者工具,基本都能使用。Chrome Dev Tools可以清晰的看到网络请求(虽然你需要一些小技巧来查看请求),也可以显示代码中的 console logsdebugger 断点。你甚至可以直接使用Redux DevTools来查看Redux数据的state。但是跟Web开发中查看DOM的inspect还没有,原生的Inspector实在有些难用。


发布

如果你开发一个适配了iOS和Android平台的App,并将其发布到App Store或者Google Play之前,你需要知道Xcode和Android Studio是怎么工作的,这样才能保证没有什么纰漏。对于iOS,跟发布一个普通的原生App没什么区别,不过在Android上,在发布到Google Play之前你需要按照React说明注册你的APK。

如果你很怀念以前在web app和VCS中那样简单的敲一行命令就能对你的原生App部署更新,你可以尝试下用Code Push将你的代码部署到用户端,这样就不需要先申请,然后发布App到Store,再等待很久才能通过。Code Push在你需要做一些优化或者bug修复的时候非常有用,但是不建议用来更新整个的feature。

结束语

React-Native用起来十分顺手,我差不多已经使用了快一年,开发起App也十分迅速。你可以在iOS和Android上像ReactJS那样快速的实现复杂的UI。我觉得从ReactJS到React-Native的学习曲线很平滑,假如你喜欢学习JavaScript框架,那就更简单了,这只是换一种方式使用React。

React-Native的社区很庞大,并且还在增长,这种技术也不会很快的消失,我推荐每一个不想依赖Cordova创建移动App的web开发者尝试一下。你会喜欢上它的!