React Native入门

692 查看

React Native使你能够利用JavaScript和React来构建原生App。即使你没有IOS或者Android开发经验,你仍然可以编写出一个很棒的App。Learn Once,Write Anywhere,其概念还是十分吸引人的。对那些缺少Native开发(Android,IOS)人员的小公司来说,React Native可以算的上一个很好的解决方案。React Native的好处不仅于此,它还具有实时更新,便于测试等好处。

因为React Native的知识点还是很复杂的,一两篇文章根本讲不清,所以自己决定写几篇React Native的文章(主要基于Android),或者说是笔记,既可以加深自己的理解,同时也可以让更多人的了解React Native.目前完成的文章如下,欢迎大家持续关注,如果有什么疏漏或者错误还请指出:

例子

下面是React Native项目的入口文件(Android为index.android.js,IOS为index.ios.js)

//表示导入,类似java import
import React, {
  Component,
} from 'react';

//解构式赋值,表示AppRegistry,Image...存在于react-native中,那么在文件中就可以用Image来代替ReactNative.Image.
import {
  AppRegistry,
  Image,
  ListView,
  StyleSheet,
  Text,
  View,
} from 'react-native';

var API_KEY = '7waqfqbprs7pajbz28mqf6vz';
var API_URL = 'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json';
var PAGE_SIZE = 25;
var PARAMS = '?apikey=' + API_KEY + '&page_limit=' + PAGE_SIZE;
var REQUEST_URL = API_URL + PARAMS;

class demoReact extends Component {
  //构造器
  constructor(props) {
    super(props);
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false,
    };
  }

  //React 生命周期的一个方法,它会在组件刚加载完成之后调用一次,以后不会再调用
  componentDidMount() {
    this.fetchData();
  }

  fetchData() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          dataSource: this.state.dataSource.cloneWithRows(responseData.movies),
          loaded: true,
        });
      })
      .done();
  }

  //利用JSX方式渲染UI
  render() {
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderMovie}
        style={styles.listView}
      />
    );
  }

  renderLoadingView() {
    return (
      <View style={styles.container}>
        <Text>
          Loading movies...
        </Text>
      </View>
    );
  }

  renderMovie(movie) {
    return (
      <View style={styles.container}>
        <Image
          source={{uri: movie.posters.thumbnail}}
          style={styles.thumbnail}
        />
        <View style={styles.rightContainer}>
          <Text style={styles.title}>{movie.title}</Text>
          <Text style={styles.year}>{movie.year}</Text>
        </View>
      </View>
    );
  }
};

//声明样式,用来构建布局
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  rightContainer: {
    flex: 1,
  },
  title: {
    fontSize: 20,
    marginBottom: 8,
    textAlign: 'center',
  },
  year: {
    textAlign: 'center',
  },
  thumbnail: {
    width: 53,
    height: 81,
  },
  listView: {
    paddingTop: 20,
    backgroundColor: '#F5FCFF',
  },
});

//将项目注册到原生工程中
AppRegistry.registerComponent('demoReact', () => demoReact);

上面的代码是官网上的官方教程,你需要通过它了解的是:

  • 导入项目所需要的文件,如react,react-native
  • 继承一个基本组件
  • 声明样式
  • 渲染UI
  • 调用API

怎么样,是不是还挺简单的,那么,接下来介绍几个关键的概念:

Virtual DOM

在看渲染UI的代码的时候,你可以发现它和依赖于浏览器的DOM相似,可又有所不同,可以称它为Virtual DOM.它具有以下几种特点:

  • Virtual DOM本身不依赖于浏览器环境,它可以运行在任何JavaScript的执行环境。
  • 每当数据变化时,React会将当前的虚拟数和上一次构建的进行Diff,然后得出DOM的区别,最后将需要变化的部分进行实际的浏览器DOM更新,这样实际上减少了DOM的操作,运行性能得到提高。将管理DOM的操作交给框架来做,这样减少了开发人员维护DOM的工作量,使开发人员只要关心数据即可,提高了工作效率。
  • 合并处理事件。举个例子,你将节点内容从A变成B,再将B变成A,那么React会认为什么都没有改变。

Component

React信奉组件化的开发思路。所谓的Thinking in React,就是要求你以组件化的思路来构建你的应用---将你UI中每个功能或者UI进行拆分,封装,从而叨叨复用或者逻辑分离的目的。组件化的开发特点如下:

  • 每个组件的UI和逻辑都定义在组件内部,和外部完全通过预先设计好的机制来交互,通过组合的方式来实现复杂的功能。
  • React组件,就是 个简单的状态机器。组件核心包括render方法、props(外部传 入的属性)和states(组件本身的状态)。
  • 当组件处于某个状态时,那么就输出这个状态对应的界面。当某个状态发生变化后,
    React会自动会更新界面。
  • 具体可参考Android和IOS的界面设计

单向数据流动

既然已经有了组件机制去定义界面 ,那么还需要一定的机制来定义组件之间,以及组件和数据模型之间如何通信。为此,Facebook提出了Flux框架用于管理数据流。不同于其它MVC框架的双向数据绑定,Flux提倡的是单向数据流动,即永远只有从模型到视图的数据流动。

其他值得注意的点

异步执行

在Javascript代码和原生平台之间的所有操作都是异步执行的,并且原生模块还可以根据需要创建新的线程。这意味着你可以在主线程解码图片,然后在后台将它保存到磁盘,或者在不阻塞UI的情况下计算文字大小和界面布局等等。所以React Native开发的app天然具备流畅和反应灵敏的优势。Javascript和原生代码之间的通讯是完全可序列化的,这使得我们可以借助Chrome开发者工具去调试应用,而不论应用运行在模拟器还是真机上。

样式中实现了Flexbox

在React Native你基本上可以使用Web中常见的样式,React Native借鉴了弹性盒模型,具体讲解请看这篇文章

首先,React Native没有实现css来渲染样式,而是使用JavaScript声明样式,像下面这样:

var styles = StyleSheet.create({
  container: {
    flexDirection: 'row',  
    flexWrap:'wrap',
    justifyContent:'center',
    alignItems:'center', 
    flex:1, 
    backgroundColor:'#120056',
  },
  item:{
    width:75,
    height:75,
    color:'#ffffff',
    backgroundColor:'#234567',
    margin:10,
  },
  special:{
    width:75,
    height:75,
    color:'#ffffff',
    backgroundColor:'#234567',
    margin:10,
    alignSelf:'flex-end',
  },
});

然后在这里利用自己定义好的样式 :

  <View style={styles.container}>
    <Text style={styles.item}>
      1
    </Text>
    <Text style={styles.item}>
      2
    </Text>
    <Text style={styles.item}>
      3
    </Text>
    <Text style={styles.special}>
      4
    </Text>
    <Text style={styles.item}>
      5
    </Text>
  </View>

JavaScript环境

React Native内置了Babel JavaScript Compiler.因此你可以使用ES5,ES6,ES7上面最新的语法,而不用担心环境是否支持。
另外值得注意一点的就是你可以在React中使用JSX,它是一个让你可以用类似XML的方式写view的JavaScript扩展。

原生模块进行交互,创建原生View

React Native也可以让你很方便的同Native进行交互,创建原生View。

React Native手势响应系统

React Native的触摸系统让你有接近原生的触摸体验。