作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
约翰内斯·斯坦的头像

Johannes Stein

Johannes是两本书的作者,也是一名精通JS的高技能软件架构师, web tech, 以及跨平台开发.

Previously At

Gamesys
Share

当React Native发布时,第一反应是压倒性的积极. 传统上,当我们想到移动领域的网络技术,就像 Apache Cordova spring to mind, 这使得我们可以将网站或web应用程序打包为移动平台的应用程序. 在这个React Native新手教程中, 我们将了解React Native背后的架构和哲学, 以及它与同一空间中的其他解的不同之处. 在文章的最后, 我们将把一个React“Hello World”应用转换成一个React Native应用.

让我们从React Native基础开始. 它已于2015年3月正式推出, 自那年年初以来一直处于内测阶段, 并在Facebook内部使用了一段时间. “罗马不是一天建成的”这句话也适用于技术. Tools like grunt 和Node这样的平台.j花了很多年才成熟. 在网络世界里, 事情进展很快, 并且有大量的框架, packages, 每天都有新工具问世, developers 倾向于变得更加怀疑,不想跳上每一个炒作的潮流,只是意识到他们最终陷入了供应商锁定的局面. 我们会讲到React Native的特别之处, 为什么这是一项值得研究的技术, 并涵盖一些不全是独角兽和彩虹的例子.

Under the Hood

当谈到移动网络技术时, 可用的解决方案通常属于以下类别之一.

在移动Web浏览器中捆绑Web应用程序

web应用程序驻留在移动浏览器中,通常称为WebView. 无需任何重大重构,网站或web应用程序就可以在移动设备上运行. 我们可能需要考虑移动浏览器事件,如点击或收听设备方向变化和更小的屏幕,以获得完整的用户体验, 但我们有一个工作的手机版本,以最小的努力. Cordova/PhoneGap是这个类别中最受欢迎的选择. 不幸的是,这个选项有一个很大的缺点:在某些情况下, 使用Cordova开发的应用程序比本机应用程序要慢得多, 特别是对于图形化的应用程序. In other cases, 移动操作系统实际上并没有提供WebView中所有移动浏览器中可用的功能. The user experience can also differ from native applications; this may happen due to the application or the platform itself. 这个问题可能从滚动条感觉不一样到点击元素时有明显的延迟.

编译到本地技术

一个完全不同的解决方案是最终创建一个本地代码库. 这是通过将原始源代码转换为另一种编程语言来实现的. 我们用原生性能换取了具有一些不确定性的抽象层. 对于闭源解决方案, 我们甚至不确定引擎盖下发生了什么,以及我们正在处理的是什么样的黑匣子. 在其他情况下,我们不确定下一个移动操作系统更新会在多大程度上破坏我们的代码,也不确定修复或更新何时可用. 这个类别的一个流行的例子是 Haxe.

使用JavaScript图层

在这里,我们使用移动环境的JavaScript引擎并在那里执行我们的JavaScript. 本地控件被映射到JavaScript对象和函数, 当我们调用一个函数时 fancyButtonRightHere (),屏幕上会出现一个按钮. NativeScript或Appcelerator Titanium就是这一类的著名例子.

React Native可以被归类为第三类. 适用于iOS和Android版本, React Native在底层使用JavaScriptCore, iOS上的默认JavaScript引擎是什么. JavaScriptCore也是苹果Safari浏览器中的JavaScript引擎. OS X and iOS developers 如果他们想,可以直接与它交互吗.

一个很大的区别是 React Native 在一个单独的线程中运行JavaScript代码, 所以用户界面不会阻塞,动画也应该流畅.

React是关键特性

值得注意的是,React Native中的“React”并不是偶然出现的. 要学习React Native,我们需要了解React到底提供了什么. 以下概念在React和React Native中是相同的, 尽管这些代码示例是为在浏览器中运行而定制的.

单渲染入口点

当我们看一个简单的React组件时, 我们可能注意到的第一件事是组件有一个 render function. 事实上,如果组件中没有定义呈现函数,React就会抛出一个错误.

var MyComponent = function() {
  this.Render = function() {
    //在这里渲染
  };
};

这里的特殊之处在于我们没有使用DOM元素, 但是我们返回一个基于xml的结构,它表示将在DOM中呈现的内容. 这种基于xml的构造称为JSX.

var MyComponent = function() {
  this.Render = function() {
    return 
Hello there
; }; };

一个特殊的JSX转换器接收所有看起来像xml的代码并将其转换为函数. 这就是转换后的组件的样子:

var MyComponent = function() {
  this.Render = function() {
     return React.createElement (" div ", {
       名称:“组件”
     }, "Hello there");
  };
};

最大的优点是通过快速查看组件, 我们总是知道它应该做什么. For example a 组件可能呈现许多 components. 我们不能在其他任何地方渲染组件,只能在 render function, 所以从来没有担心我们不知道我们渲染的组件到底来自哪里.

单向数据流

为了构建组件的内容,React提供了属性或道具. 类似于XML属性, 我们直接将props传递给组件,然后可以在构建的组件中使用这些props.

var Hello = function(props) {
  this.Render = function() {
    return 
Hello {props.name}
; }; }; var Greeter = function() { this.Render = function() { return } };

这导致我们的组件处于树状结构中, 并且只允许在构造子元素时传递数据.

更改后重新渲染

除了道具,组件也可以有内部状态. 这种行为最突出的例子是点击计数器,当按钮被按下时,它会更新其值. 点击次数本身将保存在状态中.

每个道具和状态的改变都会触发组件的完全重新呈现.

Virtual DOM

现在,当道具或状态改变时,所有东西都被重新渲染, 为什么React本身表现得这么好? 神奇的成分是“虚拟DOM”.“每当有东西需要重新渲染时, 生成更新后DOM的虚拟表示. Virtual DOM包含了按照组件树建模的元素的简单表示, 使得生成它们的过程比生成真正的DOM元素要高效得多. 在将更改应用于实际DOM之前, 执行检查以确定更改发生在组件树中的确切位置, 创建一个diff, 只有那些特定的变化才会被应用.

开始使用这个React Native初学者教程

为了在这个框架中开发,初学者需要设置一些先决条件. 因为iOS是第一个支持的平台, 以及我们将在React Native教程中介绍的, 我们需要macOS和Xcode, 至少版本6.3. Node.Js也是必需的. 有帮助的是安装 Watchman 通过Brew包管理器 Brew安装watchman. 虽然这并不是必须的, 它在处理React Native项目中的大量文件时很有帮助.

React Native:最健全的移动应用开发框架.

要安装React Native,我们只需要 安装React Native命令行应用程序 with NPM install -g react-native-cli. Calling the react-native 命令,然后帮助我们创建一个新的React Native应用. Running react-native init HelloWorld 创建一个名为 HelloWorld 在其中可以找到样板代码.

演示如何设置React Native“Hello World”应用程序的终端动画.

转换React应用程序

React是关键特性,核心原理来自React库, 让我们来看看把一个最小的React“Hello World”应用转换成一个React Native应用需要做些什么.

在这个代码示例中,我们使用了一些ES2015的特性,特别是类. 坚持下去是完全可行的 React.createClass 或者使用类似于流行的模块模式的函数形式.

var React = require(' React ');

HelloThere类扩展React.Component {
  clickMe() {
    alert('Hi!');
  }
  render() {
    return (
      
Hello {this.props.name}. 请点击我.
); } } React.render(, document.getElementById(“内容”));

步骤1:拥抱CommonJS模块

在第一步中,我们需要更改需要使用的React模块 react-native instead.

var React = require(' React -native');

HelloThere类扩展React.Component {
  clickMe() {
    alert('Hi!');
  }
  render() {
    return (
      
Hello {this.props.name}. 请点击我.
); } } React.render(, document.getElementById(“内容”));

当开发React web应用程序是React Native不可分割的一部分时,工具管道的一部分通常是什么.

步骤2:没有DOM

毫不奇怪,移动设备上没有DOM. 我们之前使用的地方

,我们需要使用 我们用过的地方 ,我们需要的分量是 .

从“React”中导入React;
从' react-native'中导入{View, Text, Alert};

HelloThere类扩展React.Component {
  clickMe() {
    Alert.alert(‘hi!');
  }
  render() {
    return (
      Hello {this.props.name}. 请点击我.
    );
  }
}

React.render(, document.getElementById(“内容”));

直接输入文本非常方便

元素,在原生世界中文本不能直接放在 . 为此,我们需要插入a component.

从“React”中导入React;
从' react-native'中导入{View, Text, Alert};

HelloThere类扩展React.Component {
  clickMe() {
    Alert.alert(‘hi!');
  }
  render() {
    return (
      
        Hello {this.props.name}. 请点击我.
      
    );
  }
}

React.render(, document.getElementById(“内容”));

步骤3:内联样式是最好的选择

React Native允许我们使用Flexbox建模,而不是乱用 float and inline-block 我们在网络世界中非常熟悉. 有趣的是,React Native不使用CSS.

从“React”中导入React;
import {View, Text, StyleSheet, Alert} from ' react-native';

HelloThere类扩展React.Component {
  clickMe() {
    Alert.alert(‘hi!');
  }
  render() {
    return (
      
        Hello {this.props.name}. 请点击我.
      
    );
  }
}

var styles =样式表.create({
  box: {
    borderColor:“红”,
    写成backgroundColor:“# fff ',
    borderWidth: 1、
    padding: 10,
    width: 100,
    height: 100
  }
});

React.render(, document.getElementById(“内容”));

对于初学者来说,使用内联样式似乎令人困惑. 这类似于React开发人员在面对JSX和之前使用Handlebars或Jade等模板引擎时所经历的转变.

我们的想法是,在使用CSS的方式中,我们没有全局的样式表. 我们直接在组件级别声明样式表, 这样我们就有了所有我们需要的信息来看看我们的组件是做什么的, 它创建的布局, 以及它所应用的样式.

从“React”中导入React;
从' react-native'中导入{Text};

var标题= function(props) {
  this.render = () => {props.caption};
};

var headlinestyle =样式表.create({
  text: {
    fontSize: 32,
    fontWeight:“大胆”
  }
});

module.exports =标题;

步骤4:处理事件

在移动设备上点击一个元素,相当于在网页上点击. 让我们修改一下代码,以便在点击元素时弹出“alert”.

从“React”中导入React;
从' react-native'中导入{View, Text, StyleSheet, touchableacity, Alert};

HelloThere类扩展React.Component {
  clickMe() {
    Alert.alert("Hi!")
  }
  render() {
    return (
      
        
          Hello {this.props.name}. 请点击我.
        
      
    );
  }
}

var styles =样式表.create({
  box: {
    borderColor:“红”,
    写成backgroundColor:“# fff ',
    borderWidth: 1、
    padding: 10,
    width: 100,
    height: 100
  }
});

React.render(, document.getElementById(“内容”));

而不是直接在 components, 我们需要显式地使用触发事件的元素, 在我们的例子中,按下视图时的触摸事件. 有不同类型的可触摸组件可用, 每一个都提供了不同的视觉反馈.

步骤5:定制跨平台行为

的值可以检测应用程序运行在哪个平台上 Platform.OS. Let’s say that, 在上面的React Native代码示例中, 我们希望根据我们运行的平台显示不同的警报消息. 我们可以这样做:

...
clickMe() {
  Var message = ";
  if(Platform.OS == ‘ios') {
    message =‘欢迎来到iOS!';
  } else if(平台.OS == ' android') {
    欢迎使用Android!';
  }   
  Alert.警报(消息);
}
...

或者, select 方法也可用,它提供了一个类似开关的语法:

…
clickMe() {
  Alert.alert(Platform.select({
    ios:欢迎来到ios!',
    android:欢迎来到android!'
  })
  );
}
...

为了添加自定义字体,我们需要克服一些困难. First of all, 确保字体的全名和字体的文件名相同:iOS将使用字体的全名来挑选字体, 而Android使用文件名.

如果字体的全名是 myCustomFont,确保字体的文件名为 myCustomFont.ttf.

之后,我们需要创建一个assets文件夹,并把npm指向它. 我们可以先创建文件夹,在 assets/fonts 在应用程序的根目录中. 任何其他目录都可以,但这是用于字体目录的常规名称.

我们可以通过添加an来告诉npm我们的资源在哪里 Assets 属性rnpm:

"rnpm": {
  "Assets": [
    "./ /字体/资产”
  ]
}

做完这些之后,我们终于可以跑了 react-native链接. 这将复制字体到正确的目录,并将必要的xml添加到info.plist on iOS.

完成后,我们可以通过在任何样式表中引用字体的全名来使用字体. 我们用它 Text element:

从“React”中导入React;
从' react-native'中导入{View, Text, StyleSheet, touchableacity, Alert};

HelloThere类扩展React.Component {
  clickMe() {
    Alert.alert("Hi!")
  }
  render() {
    return (
      
        
          Hello {this.props.name}. 请点击我.
        
      
    );
  }
}

var styles =样式表.create({
  box: {
    borderColor:“红”,
    写成backgroundColor:“# fff ',
    borderWidth: 1、
    padding: 10,
    width: 100,
    height: 100
  },
  message: {
    fontFamily:“myCustomFont”
  }
});

React.render(, document.getElementById(“内容”));

第七步:移动物品

React Native使用与Flexbox相同的规则来布局组件. 假设我们想要将按钮定位在屏幕的底部:让我们包装我们的 TouchableOpacity 用一个容器 View:


    
        
            Hello {this.props.name}. 请点击我.
        
    

现在我们来定义 container 样式,连同其他已定义的样式:

container: {
    flex: 1,
    justifyContent:“中心”,
    alignItems:“中心”
  }

Let’s focus on justifyContent and alignItems. 这两个属性分别控制组件沿其主轴和副轴的对齐方式. By default, 主轴是垂直的, 副轴是水平轴(你可以通过设置 flexDirection property to row).

justifyContent 有六个可能的值可以设置为:

  • flex-start 将所有的元素放在一起,在组件的边界框的开始.
  • flex-end 将所有元素放置在最后.
  • center 是否将所有元素放置在边界框的中心.
  • space-around 将组件均匀分布,并将组件置于其创建的边界框的中心.
  • space-evenly 也会均匀地散布这些成分吗, 但它会尝试在分量和其他边界之间留下等量的空间.
  • space-between 将通过保持相邻分量之间的间距相等来展开分量吗.

alignItems 可以设置为四个可能的值: flex-start, flex-end, center, and stretch. 前三个的行为就像 justifyContent, while stretch 是否将组件设置为占用沿轴的所有可用空间, 这样轴就被填满了.

既然我们想要 TouchableOpacity 显示在底部并沿水平轴居中, 我们可以像这样改变样式:

container: {
  flex: 1,
  justifyContent:“flex-end”,
  alignItems:“中心”
}

有关值的更多信息 justifyContent and alignItems 能有能找吗 here and here.

步骤8:注册应用程序

当使用React为浏览器开发时,我们只需要定义一个挂载点,调用 React.render,让React发挥它的魔力. 在React Native中,这有点不同.

从“React”中导入React;
import {View, Text, StyleSheet, touchableacity, Alert, Platform} from ' react-native';

HelloThere类扩展React.Component {
  clickMe() {
    Alert.alert(Platform.select({
      ios:欢迎来到ios!',
      android:欢迎来到android!'
    }));
  }

  render() {
    return (
      
        
          
            Hello {this.props.name}. 请点击我.
          
        
      
    );
  }
}

var styles =样式表.create({
  container: {
    flex: 1,
    justifyContent:“flex-start”,
    alignItems:“中心”
  },
  box: {
    borderColor:“红”,
    写成backgroundColor:“# fff ',
    borderWidth: 1、
    padding: 10,
    width: 100,
    height: 100
  },
  message: {
    fontFamily:“myCustomFont”
  }
});

var MainComponent = function() {
  this.Render = function() {
    return ;
  }
};

AppRegistry.registerComponent('MainComponent', function() {
  返回MainComponent;
});

我们必须为Objective-C方面的东西注册组件,这是使用 AppRegistry object. 我们给出的名称必须与Xcode项目中的名称相匹配.

我们的Hello World React Native应用程序比web应用程序的代码行数要多得多, 但另一方面, React Native在关注点分离方面更进一步, 特别是因为样式是与组件一起定义的.

顺便说一句,我们不应该重新绑定 clickMe method to the this context in the render 方法,特别是当我们的React (Native)应用程序变得更复杂时. 它在每个渲染调用上重新绑定方法,这可能会变得相当多. 另一种方法是在构造函数中绑定方法.

运行应用程序

要运行应用程序,我们需要替换 index.ios.js 文件中包含上一步转换后的应用程序的代码片段. 然后我们只需要打开Xcode项目并按下Run按钮. 首先,将打开带有React Native服务器的终端,然后将出现模拟器窗口. React Native服务器创建一个bundle,然后本地应用程序将获取它. 这允许类似于web开发的快速开发周期, 哪些改动会在模拟器中立即反映出来.

对于Android,只需在你的 package.json file, under scripts:

react-native包——platform android——dev false——entry-file index.ios.——bundle-output android / app / src / main /资产/index.android.Bundle——assets-dest android/app/src/
main/res && react-native运行android”

And then run NPM运行android-linux. Make sure the android / app / src / main /资产 事先存在目录.

在终端弹出后,我们的应用程序将显示在模拟器中. 按CMD+D将显示一个开发菜单. 然后单击该框将显示一个警告. iOS版本:

苹果手机会弹出提示“嗨”."

Android呈现的是这样的:

Android手机会弹出提示“嗨”."

对分布, 拥有一个指向本地开发服务器的应用程序对我们来说是行不通的. 出于这个原因, 当React Native服务器没有运行该命令时,我们可以创建bundle来使用 react-native包. 在这种情况下,我们需要更新 didFinishLaunchingWithOptions method of AppDelegate 使用脱机包.

这个示例应用程序也是 可以在Github上找到.

使用React Native

另一件值得一提的事情是,我们不仅在移动应用程序中使用React概念和JavaScript, 但是web开发人员习惯的一些工作流也可以在React Native中使用. 当来自于web开发时, 我们已经习惯了开发人员工具, 检查元素, 实时装填.

React Native的工作方式是把我们所有的JavaScript文件放在一个bundle中. 该包要么从服务器提供,要么与应用程序捆绑在一起. 第一个对于在模拟器中开发非常有用,因为我们可以启用实时重新加载. React提供的开发者菜单远不如Chrome开发者工具强大, 但它提供了一个非常像web的开发者体验,实时重新加载和 debugging 使用Chrome(或Safari)开发/调试工具.

Web开发人员熟悉JSFiddle或JSBin,这是一个用于快速Web测试的在线平台. There is 相似的环境 它允许我们在web浏览器中试用React Native.

React Native:一个可靠的、现代的选择

我最初建议采用一种更谨慎的方法来使用React Native. 今天,这是一个成熟而坚实的选择.

React的一大优点是它不会对你的工作流程产生影响, 因为它只代表视图层. 您想定义自己的Grunt管道吗? 或者你更愿意使用Webpack? 你会使用Backbone吗.为您的模型需要? 或者您想要使用纯JavaScript对象? 所有这些问题的答案完全取决于你, 因为React对这些选择没有任何限制. 正如官方网站所说:“因为React对你的技术栈的其余部分没有任何假设, 在现有项目中的一个小特性上进行测试是很容易的.”

在某种程度上,React Native也是如此. 移动开发者可以将React Native集成到他们的应用中, 利用受web启发的开发工作流程, 如果需要的话,选择在更大的范围内整合图书馆.

无论如何,有一件事是肯定的: React Native不会消失. Facebook在应用商店中拥有多款基于React native的应用,这对Facebook来说意义重大. React Native的社区非常庞大,而且还在不断增长.

了解基本知识

  • 什么是React Native?

    React Native是一个使用JavaScript构建原生iOS和Android应用程序的框架. 它基于与React相同的概念, 但使用本地组件而不是web组件来呈现用户界面(UI)。.

  • What is React?

    React是一个前端JavaScript库, 围绕使用声明性视图的概念设计,以提高效率和可预测性.

  • React Native和Native孰优孰劣?

    如果您支持多个平台, React Native在重用应用程序的核心代码方面提供了坚实的优势. 您可能仍然需要提供一些特定于平台的代码, 但比起为每个平台编写原生应用,编写和维护的工作量肯定更少.

  • 什么是本机应用程序?

    原生应用是针对目标平台编译并直接在其上运行的应用. 默认情况下,它将具有适合平台的“外观和感觉”. React Native旨在为您提供相同的本机外观和感觉,同时还提供额外的可移植性和熟悉的方法.

就这一主题咨询作者或专家.
预约电话
约翰内斯·斯坦的头像
Johannes Stein

Located in 英国伦敦

Member since June 30, 2014

作者简介

Johannes是两本书的作者,也是一名精通JS的高技能软件架构师, web tech, 以及跨平台开发.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Previously At

Gamesys

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal开发者

加入总冠军® community.