React Native系列教程(一)入门

2015年07月10日

React Native使你可以在本地平台上利用JavaScript和React构建拥有世界级体验的应用程序。React Native关注的是提升程序员跨平台开发的效率,达到learn once, write anywhere的目标,Facebook已经利用React Native完成了多个产品的开发,并会持续对React Native进行投入。

本地的iOS组件

通过React Native,你可以使用iOS的标准平台组件,例如UITabBar和UINavigationController。这会使你的应用程序和平台生态系统其他App保持一致的外观和体验,并且保持很高的质量。这些组件很容易通过React组件方式集成到你的应用程序中,例如TabBarIOS和NavigatorIOS。

var React = require('react-native');
var { TabBarIOS, NavigatorIOS } = React;

var App = React.createClass({
  render: function() {
    return (
      <TabBarIOS>
        <TabBarIOS.Item title="React Native" selected={true}>
          <NavigatorIOS initialRoute= />
        </TabBarIOS.Item>
      </TabBarIOS>
    );
  },
});  

异步执行

JavaScript应用代码和本地平台之间的所有操作都是被异步执行的,同时,本地模块也能很好的使用附加线程,这意味着我们能够在主线程之外进行图片解码,在后台保存到磁盘,在不阻塞主线程的情况下测量文本并计算布局等等。这样,React Native应用程序就能够保持自然顺滑,反应灵敏。这之间的通讯是完全序列化的,这样就允许我们在真机或者模拟器上运行程序时对Chrome Developer Tools施加影响进行JavaScript调试。

触摸处理

iOS拥有十分强大的相应链系统,去处理层级复杂视图的触摸响应,这是WebView所不具备的。React Native实现了一个相似的相应系统,提供了高级别的组件,例如TouchableHighlight去整合滚动视图和其他元素的属性,而不需要附加的配置。

var React = require('react-native');
var { ScrollView, TouchableHighlight, Text } = React;

var TouchDemo = React.createClass({
  render: function() {
    return (
      <ScrollView>
        <TouchableHighlight onPress={() => console.log('pressed')}>
          <Text>Proper Touch Handling</Text>
        </TouchableHighlight>
      </ScrollView>
    );
  },
});

Flexbox和风格

布局视图应该是简单的,这也是为什么我们将Flexbox布局模式从web端引入React Native. Flexbox使布局变得简单,例如stacked和nested boxes的margin和padding。React Native同样支持通用web风格,例如fontWeight,样式表抽象的提供了一种声明样式的优化机制,使组件能够顺利的使用他们,并以内联的方式应用样式。

var React = require('react-native');
var { Image, StyleSheet, Text, View } = React;

var ReactNative = React.createClass({
  render: function() {
    return (
      <View style={styles.row}>
        <Image
          source=
          style={styles.image}
        />
        <View style={styles.text}>
          <Text style={styles.title}>
            React Native
          </Text>
          <Text style={styles.subtitle}>
            Build high quality mobile apps using React
          </Text>
        </View>
      </View>
    );
  },
});
var styles = StyleSheet.create({
  row: { flexDirection: 'row', margin: 40 },
  image: { width: 40, height: 40, marginRight: 10 },
  text: { flex: 1, justifyContent: 'center'},
  title: { fontSize: 11, fontWeight: 'bold' },
  subtitle: { fontSize: 10 },
});

Polyfills

React Native专注于改变视图代码的编写方式。除此之外,我们在适当地方审视并参考了web上的通用标准,以及polyfill API。你可以利用npm去安装javascript库,并在React Native中使用,例如 XMLHttpRequest, window.requestAnimationFrame以及 navigator.geolocation。我们正在不断的完善扩展这些API,并且期待这开源社区也能够做出贡献。

var React = require('react-native');
var { Text } = React;

var GeoInfo = React.createClass({
  getInitialState: function() {
    return { position: 'unknown' };
  },
  componentDidMount: function() {
    navigator.geolocation.getCurrentPosition(
      (position) => this.setState({position}),
      (error) => console.error(error)
    );
  },
  render: function() {
    return (
      <Text>
        Position: {JSON.stringify(this.state.position)}
      </Text>
    );
  },
});

可扩展性

使用React Native构建应用程序而不写一行本地代码当然是可以的,但是React Native也被设计成很容易被本地view和模块进行扩展,这意味着你可以重用现有的代码,并且可以导入和使用任何你喜欢的本地类库。去创建一个简单的模块,只需要创建一个新的类型实现RCTBridgeModule协议,并在RCTEXPORTMETHOD中包装一个要用在JavaScript中的方法。并且类型本身也需要被RCTEXPORTMODULE()明确的导出。

// Objective-C

#import "RCTBridgeModule.h"

@interface MyCustomModule : NSObject <RCTBridgeModule>
@end

@implementation MyCustomModule

RCT_EXPORT_MODULE();

// Available as NativeModules.MyCustomModule.processString
RCT_EXPORT_METHOD(processString:(NSString *)input callback:(RCTResponseSenderBlock)callback)
{
  callback(@[[input stringByReplacingOccurrencesOfString:@"Goodbye" withString:@"Hello"]]);
}
@end
// JavaScript

var React = require('react-native');
var { NativeModules, Text } = React;

var Message = React.createClass({
  getInitialState() {
    return { text: 'Goodbye World.' };
  },
  componentDidMount() {
    NativeModules.MyCustomModule.processString(this.state.text, (text) => {
      this.setState({text});
    });
  },
  render: function() {
    return (
      <Text>{this.state.text}</Text>
    );
  }
});

自定义的iOS视图可以被RCTViewManager的子类暴露出来,实现一个-(UIView *)view方法,以及一个RCTEXPORTVIEW_PROPERTY宏类型的导出属性。最后就是一个简单的JavaScript文件连接点。

// Objective-C

#import "RCTViewManager.h"

@interface MyCustomViewManager : RCTViewManager
@end

@implementation MyCustomViewManager

RCT_EXPORT_MODULE()

- (UIView *)view
{
  return [[MyCustomView alloc] init];
}

RCT_EXPORT_VIEW_PROPERTY(myCustomProperty, NSString);
@end
// JavaScript

var React = require('react-native');
var { requireNativeComponent } = React;

class MyCustomView extends React.Component {
  render() {
    return <NativeMyCustomView {...this.props} />;
  }
}
MyCustomView.propTypes = {
  myCustomProperty: React.PropTypes.oneOf(['a', 'b']),
};

var NativeMyCustomView = requireNativeComponent('MyCustomView', MyCustomView);
module.exports = MyCustomView;