用React Native开发一个应用

作者: PlusNie | 来源:发表于2016-06-02 15:01 被阅读993次

    在React Native中创建“Hello World”程序

    • 创建项目
    • 使用Xcode
    • 使用模拟器

    React基础

    应用中会用到的组件列表。

    import React, {
      AppRegistry,
      Component,
      StyleSheet,
      Text,
      View
    } from 'react-native';
    
    • render函数

    使用以下这段代码,我们能够创建一个自定义组件:

      class GithubFinder extends Component {
            render() {
                return (
                  <View style={styles.container}>
                    <Text style={styles.welcome}>
                      Welcome to React Native!
                    </Text>
                    <Text style={styles.instructions}>
                      To get started, edit index.ios.js
                    </Text>
                    <Text style={styles.instructions}>
                      Press Cmd+R to reload,{'\n'}
                      Cmd+D or shake for dev menu
                    </Text>
                  </View>
                );
           }
      }
    

    在这个组件中,我们只包含了一个方法:render,这个方法没有参数,只是简单地返回我们希望这个组件渲染出来的视图。

    • 样式

    在我们的组件中,我们能够看到styles属性。我们在文件底部定义他们的取值:

      const styles = StyleSheet.create({
        container: {
          flex: 1,
          justifyContent: 'center',
          alignItems: 'center',
          backgroundColor: '#F5FCFF',
        },
        welcome: {
          fontSize: 20,
          textAlign: 'center',
          margin: 10,
        },
        instructions: {
          textAlign: 'center',
          color: '#333333',
          marginBottom: 5,
        },
      });
    

    调用StyleSheet.create函数能够创建很多不同的样式规则,可以把它们想成CSS规则,用来在每个条目中定义不同的样式。这里flex是Flexbox的属性,可以用来定义内容在视图中的布局,比如将一个项目放到另一个项目的左边,或者诸如此类的事情。我们可以通过styles.container来定义相应View组件的样式。
    对于已经做过Objective-C开发的人来说,这种类似CSS的样式定义方式要比使用接口来构建样式容易得多,它将节省我们大量的时间。除此之外,我们不需要重新加载整个应用来查看样式的变化,只需要在模拟器中使用Cmd+R组合键就可以看到文本的变化了,太神奇了!
    注意,React CSS是常用CSS的一个子集。可以看到,大多数的属性会稍微修改一下名称,比如text-align会写成textAlign。

    • 注册组件

    最后,在文件的末尾有这样一行代码:

    AppRegistry.registerComponent('GithubFinder', () => GithubFinder);
    

    AppRegistry.registerComponent方法用来注册我们的组件。这意味着,当iOS应用开始运行时,GithubFinder组件是出现的第一个组件。因此,当我们的应用开始运行的时候,它就知道该怎么做了。这个方法的调用一般会放到我们React Native应用代码的最后一行,基本上是开启应用的方式之一。

    • 修改组建

    现在我们已经理解组件了,让我们试着修改下它们。修改render 函数如下:

      class GithubFinder extends Component {
        render() {
          return (
            <View style={styles.container}>
              <Text style={styles.welcome}>
                This is my first custom view!
              </Text>
              <Image
               source={{uri : 'http:https://img.haomeiwen.com/i629934/74052f8714dc122c.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'}}
               style={styles.customimg}
              />
            </View>
          );
        }
      }
    

    你可能已经注意到了,当我们使用变量时,使用了{}符号。我们能通过这种方式把一个变量名添加到HTML中。在这里这么做的原因是我们想要给节点增加样式,比如说,我们提到的styles 变量,不再仅仅是简单的关键字‘styles’了。此外,对于标签中的sources属性,我们用两对{}来表示一个JavaScript对象,这个对象是用在节点属性中。
    参考下面的内容修改一下样式对象,为Image对象增加宽和高。

    const styles = StyleSheet.create({
        container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
        },
        customimg: {
        width: 200,
        height: 200
      },
    });
    

    另外还有意见要做的事,即增加我们当前使用的Image组件的声明,在文件的开头修改React 对象。如下:

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

    现在,我们应用的呆啊看起来是下面这样的:

    import React, {
      AppRegistry,
      Component,
      StyleSheet,
      Text,
      View,
      Image
    } from 'react-native';
    
    class GithubFinder extends Component {
      render() {
        return (
          <View style={styles.container}>
            <Text style={styles.welcome}>
              This is my first custom view!
            </Text>
            <Image
             source={{uri : 'http:https://img.haomeiwen.com/i629934/74052f8714dc122c.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240'}}
             style={styles.customimg}
            />
          </View>
        );
      }
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
      },
      customimg: {
        width: 200,
        height: 200
      },
    });
    
    AppRegistry.registerComponent('GithubFinder', () => GithubFinder);
    

    应用界面是这样的:

    自定义view.png

    喔!现在你已经实现了自己的第一个自定义View。

    搜索框和数据检索

    现在我们将要获取数据了,要实现这个功能,就要使用到GitHub的API,这样非常简单而且容易上手。让我们开始吧。

    • 增加搜索框

    首先,需要添加搜索框。我们将使用一个普通的TextInput和一些样式来实现搜索框。参考如下的代码来修改render 方法:

    class GithubFinder extends Component {
      render() {
        return (
          <View style={styles.container}>
            <TextInput
             autoCapitalize="none"
             autoCorrect={false} 
             placeholder="Search for a project..." 
             style={styles.searchBarInput}/>
          </View>
        );
      }
    }
    

    基本上我们创建完成了有一些不同属性的TextInpust对象,我们不需要自动填充和自动更正的功能,只需增加placeholder 文本和一些样式。样式如下:

    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: '#F5FCFF',
      },
      searchBarInput: {
        marginTop: 30,
        padding: 5,
        fontSize: 15,
        height: 30,
        backgroundColor: '#EAEAEA',
      },
    });
    

    我们修改了TextInput背景颜色来让它更明显,设置了height和margin-top,增加了padding。修改完成以后,看起来如下图:

    TextInput.png
    • 方法代理

    现在,我们需要用户在搜书框输入的时候,调用API来进行搜索。要做到这一点,我么你需要完成方法的代理绑定,就是指当有一些行为发生时执行某个函数,在当前情况下的行为就是在搜索框停止输入。要做到这一点,我们只要设置文本框的onEndEditing属性,如下:

    class GithubFinder extends Component {
      render() {
        return (
          <View style={styles.container}>
            <TextInput
             autoCapitalize="none"
             autoCorrect={false} 
             placeholder="Search for a project..." 
             style={styles.searchBarInput} 
             onEndEditing={this.onSearchChange}/>
          </View>
        );
      }
    }
    

    当搜索内容变化的时候,调用GitHub API查询结果的功能还没有实现,我们下面就来实现这个功能。

    • 检索数据

    现在我们来实现onSearchChange函数,通过GitHub的API来查询结果。如下:

    var BASE_URL = 'https://api.github.com/search/repositories?q=';
    
    class GithubFinder extends Component {
      //渲染UI
      render() {
        return (
          <View style={styles.container}>
            <TextInput
             autoCapitalize="none"
             autoCorrect={false} 
             placeholder="Search for a project..." 
             style={styles.searchBarInput} 
             onEndEditing={this.onSearchChange}/>
          </View>
        );
      },
      //检索数据
      onSearchChange: function(event: object) {
        var searchTerm = event.nativeEvent.text.toLowerCase();
        var queryURL = BASE_URL + encodeURIComponent(searchTerm);
        fetch(queryURL)
        .then((response) => response.json())
        .then((responseData) => {
          if (responseData.items) {
            this.setState({
              dataSource: this.state.dataSource.cloneWithRows(responseData.items),
            });
          };
        })
        .done();
      }
    }
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: '#F5FCFF',
      },
      searchBarInput: {
        marginTop: 30,
        padding: 5,
        fontSize: 15,
        flex: 1,
        height: 30,
        backgroundColor: '#EAEAEA',
      },
    });
    
    AppRegistry.registerComponent('GithubFinder', () => GithubFinder);
    

    显示结果

    现在我们有了自己点数据,接下来我们让结果列表形式呈现,在这个列表视图中,每一行都对应一条通过搜索GitHub返回的数据。开始吧!

    • 组建状态

    在前一节中,我们调用了this.setState方法,这是我们还没有介绍的React的一个重要概念。每一个组件都有自己的状态(state),用来存储组件的数据。在这个例子中,我们希望能够存储当前列表中显示的数据。当我们的组件首次被渲染的时候,可以通过getInitialState方法来初始化状态。如下:

    class GithubFinder extends Component {
      //组件状态
      getInitialState: function() {
        return {
          dataSource: new ListView.DataSource({
            rowHasChanged: (row1, row2) => row1 !== row2,
          }),
        };
      },
      //渲染UI
      render() {
        return (
          <View style={styles.container}>
            <TextInput
             autoCapitalize="none"
             autoCorrect={false} 
             placeholder="Search for a project..." 
             style={styles.searchBarInput} 
             onEndEditing={this.onSearchChange}/>
          </View>
        );
      },
      //检索数据
      onSearchChange: function(event: object) {
        var searchTerm = event.nativeEvent.text.toLowerCase();
        var queryURL = BASE_URL + encodeURIComponent(searchTerm);
        fetch(queryURL)
        .then((response) => response.json())
        .then((responseData) => {
          if (responseData.items) {
            this.setState({
              dataSource: this.state.dataSource.cloneWithRows(responseData.items),
            });
          };
        })
        .done();
      }
    }
    

    注意,因为我们在这里使用ListView,所以我们需要把它添加到文件最开始的组件列表中,如下:

    import React, {
      AppRegistry,
      Component,
      StyleSheet,
      View,
      TextInput
      ListView,
    } from 'react-native';
    

    在这里,我们通过属性创建了一个空白的数据源,该函数用来监控一行数据是否发生了变化。其实很简答,这个函数的作用就是:如果两次的数据不相同的话,告诉数据源该行为数据发生了变化。
    现在我们已经设置好初始状态了,而且我们的数据检索方法已经能够通过搜索结果来成功地设置数据源的内容行了。以后如果获取到新数据,就能够通过修改数据源来改变内容行的显示了。

    • 创建ListView组件

    现在,我们需要创建列表视图来显示已经加载的数据源结果。通过在render 方法中添加一个组件来实现这个效果:

      //渲染UI
      render() {
        var content;
        if (this.state.dataSource.getRowCount() === 0) {
          content =
              <Text>
                Please enter a search term to see results.
              </Text>;
        } else {
          content = 
              <ListView
                  ref="listView"
                  dataSource={this.state.dataSource}
                  renderRow={this.renderRow}
                  automaticallyAdjustContentInsets={false}
                  keyboardDismissMode="onDrag"
                  keyboardShouldPersistTaps={true}/>;
        };
        return (
          <View style={styles.container}>
            <TextInput
             autoCapitalize="none"
             autoCorrect={false} 
             placeholder="Search for a project..." 
             style={styles.searchBarInput} 
             onEndEditing={this.onSearchChange}/>
             {content}
          </View>
        );
      },
    
    • 创建每个数据单元

    现在我们要渲染每一条结果数据了。我们来实现一个方法,通过this.renderRow来完成方法的绑定,从而达到渲染数据的效果。方法的实现如下:

    renderRow: function(repo: Object) {
      return (
          <View>
              <View style={styles.row}>
                <Text> 
                  {repo.name}
                </Text>
              </View>
              <View style={styles.cellBorder} />
          </View>
        );
    },
    

    在这里,我们创建了一个基本的结果条目,用来显示搜索结果中的名称。我们给styles增加两个样式规则,row和cellBorder,用来渲染这个结果条目。

    row: {
      alignItems: 'center',
      backgroundColor: 'white',
      flexDirection: 'row',
      padding: 5,
    },
    cellBorder: {
      backgroundColor: 'rgba(0, 0, 0, 0.1)',
      height: 1,
      marginLeft: 4,
    },
    

    未完,待续。

    相关文章

      网友评论

      • 罗同学_:这货和hybrid相比哪个更适合h5app
        某个胖子:跟hybird是两个东西吧
        罗同学_:@NiePlus 好的
        PlusNie:hybrid和react-native个人青睐react-native,毕竟Facebook开源,比较成熟一些。对于hybrid还不太了解,公司项目下个版本迭代使用hybrid,等开发完后我会总结下,对比下它们。
      • 孙国庆:不错

      本文标题:用React Native开发一个应用

      本文链接:https://www.haomeiwen.com/subject/wljvlttx.html