Bootstrap

【React Native】基础知识及入门使用

起步

本节将帮助您安装和构建第一个 React Native 应用程序。如果您已经安装了 React Native,那么可以跳到本教程。

如果你是移动开发新手,最简单的入门方法是使用Expo CLI。Expo是一套围绕React Native构建的工具,虽然它有很多功能,最基础的功能是它可以让你在几分钟内编写一个React Native应用程序。你只需要Node.js的最新版本和一个手机或模拟器。如果您想在安装任何工具之前直接在web浏览器中试用React Native,可以试用[Snack](https://snack.expo.io/ Snack)。

如果您已经熟悉移动开发,那么可能需要使用React Native CLI。它需要Xcode或Android Studio才能启动。如果你已经安装了其中一个工具,您应该能够在几分钟内启动并运行。如果没有安装,您应该花大约一个小时来安装和配置它们。

使用 Expo CLI

假设已安装 Node.js 10 LTS或更高版本,则可以使用npm安装Expo CLI命令行实用程序:

npm install -g expo-cli

然后运行以下命令,创建一个名为“rn-basics”本地项目:

expo init rn-basics

cd rn-basics
npm start # 也可以使用命令: expo start

此时会启动一个开发服务器。

运行 React Native 应用程序

在iOS或Android手机上安装[Expo](https://docs.expo.io/versions/v36.0.0/get-started/installation/ Expo)客户端应用程序,并连接到与计算机相同的无线网络(Wifi热点)。在Android上,使用Expo应用程序从终端扫描二维码以打开项目。在iOS上,按照屏幕上的说明(一般为使用相机扫描)获取链接。

修改你的程序

现在你已经成功运行了应用程序,让我们修改一下代码试试。在文本编辑器中打开 App.js 并编辑一些行。保存更改后,应用程序会自动重新加载。

基础知识

React Native 与 React类似,但它使用原生(native)组件而不是基于浏览器(web)组件作为构建块。因此,要了解 React Ntive 应用程序的基本结构,您需要了解一些基本的 React 概念,如JSX、组件、状态和属性。如果你已经了解 React,那么你仍然需要学习一些 React Native 特定的东西,比如 原生(Native) 组件。本教程面向所有人群,无论你是否有 React 经验。

Hello World

编程界的老习惯,先来个 Hello World 尝尝鲜:

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

export default class HelloWorldApp extends Component {
  render() {
    return (
      <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
        <Text>Hello, world!</Text>
      </View>
    );
  }
}

如果你感到好奇,这不就是React程序吗?是的,可以直接在web模拟器中运行这段代码。也可以将其粘贴到App.js文件中,以便在本地计算机上创建真正的原生应用程序。

奇葩的语法

首先,ES2015(也称为ES6)是对JavaScript的一系列改进,ECMAScript 现在是官方标准的一部分,但还没有得到所有浏览器的支持。React Native ships 支持 ES2015,因此你可以使用这些内容而不必担心兼容性。上述示例中的import、from、class 和 extends 都是ES2015的特性。如果你不熟悉ES2015,你也可以通过阅读本教程中的示例代码来了解它。

在这个代码示例中,另一个不寻常的事情是<View><Text>Hello world!</Text></View>。这是JSX——一种在JavaScript中嵌入XML的语法。许多框架使用一种专门的模板语言,允许您在标记语言中嵌入代码。在React中,没有使用模板。JSX允许您在代码中编写标记语言。它看起来像web上的HTML,但这里使用的是React组件,而不是像<div><span>这样的 HTML 标签。在本例中,是一个内置组件,它显示一些文本,类似于<div><span>

组件

这段代码定义了HelloWorldApp,这是一个新组件。当你在构建一个 React 本地应用程序时,你将大量地生成新组件。你在屏幕上看到的任何东西都是某种组件。

State

我们使用两种数据来控制一个组件:props 和 state。props是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变。对于需要改变的数据,我们需要使用state。

一般来说,你需要在class中声明一个state对象,然后在需要修改时调用setState方法。

假如我们需要制作一段不停闪烁的文字。文字内容本身在组件创建时就已经指定好了,所以文字内容应该是一个prop。而文字的显示或隐藏的状态(快速的显隐切换就产生了闪烁的效果)则是随着时间变化的,因此这一状态应该写到state中。

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

class Blink extends Component {
  // 声明state对象
  state = { isShowingText: true };

  componentDidMount() {
    // 每1000毫秒对showText状态做一次取反操作
    setInterval(() => {
      this.setState({
        isShowingText: !this.state.isShowingText
      });
    }, 1000);
  }

  render() {
    // 根据当前showText的值决定是否显示text内容
    if (!this.state.isShowingText) {
      return null;
    }

    return (
      <Text>{this.props.text}</Text>
    );
  }
}

export default class BlinkApp extends Component {
  render() {
    return (
      <View>
        <Blink text='I love to blink' />
        <Blink text='Yes blinking is so great' />
        <Blink text='Why did they ever take this out of HTML' />
        <Blink text='Look at me look at me look at me' />
      </View>
    );
  }
}

实际开发中,我们一般不会在定时器函数(setInterval、setTimeout 等)中来操作 state。典型的场景是在接收到服务器返回的新数据,或者在用户输入数据之后。你也可以使用一些“状态容器”比如Redux来统一管理数据流。

每次调用setState时,BlinkApp 都会重新执行 render 方法重新渲染。这里我们使用定时器来不停调用setState,于是组件就会随着时间变化不停地重新渲染。

State 的工作原理和 React.js 完全一致,所以对于处理 state 的一些更深入的细节,你可以参阅React.Component API。

提示一些初学者应该牢记的要点: 一切界面变化都是状态state变化 state的修改必须通过setState()方法 this.state.likes = 100; // 这样的直接赋值修改无效! setState 是一个 merge 合并操作,只修改指定属性,不影响其他属性 setState 是异步操作,修改不会马上生效

样式

在 React Native 中,你并不需要学习什么特殊的语法来定义样式。我们仍然是使用 JavaScript 来写样式。所有的核心组件都接受名为 style 的属性。这些样式名基本上是遵循了 web 上的 CSS 的命名,只是按照 JS 的语法要求使用了驼峰命名法,例如将 background-color 改为 backgroundColor。

style属性可以是一个普通的 JavaScript 对象。这是最简单的用法,因而在示例代码中很常见。你还可以传入一个数组——在数组中位置居后的样式对象比居前的优先级更高。

实际开发中组件的样式会越来越复杂,建议使用 StyleSheet.create 来集中定义组件的样式。

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

const styles = StyleSheet.create({
  bigBlue: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 30,
  },
  red: {
    color: 'red',
  },
});

export default class LotsOfStyles extends Component {
  render() {
    return (
      <View>
        <Text style={styles.red}>just red</Text>
        <Text style={styles.bigBlue}>just bigBlue</Text>
        <Text style={[styles.bigBlue, styles.red]}>bigBlue, then red</Text>
        <Text style={[styles.red, styles.bigBlue]}>red, then bigBlue</Text>
      </View>
    );
  }
}

常见的做法是按顺序声明和使用style属性,以借鉴 CSS 中的“层叠”做法(即后声明的属性会覆盖先声明的同名属性)。

使用 Fetch

React Native 提供了和 web 标准一致的 Fetch API,用于满足开发者访问网络的需求。

发起请求

要从任意地址获取内容的话,只需简单地将网址作为参数传递给 fetch 方法即可(fetch 这个词本身也就是获取的意思)

fetch('https://mywebsite.com/mydata.json');

Fetch 还有可选的第二个参数,可以用来定制 HTTP 请求一些参数。你可以指定 header 参数,或是指定使用 POST 方法,又或是提交数据等等:

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    firstParam: 'yourValue',
    secondParam: 'yourOtherValue',
  }),
})

提交数据的格式关键取决于 headers 中的Content-Type。Content-Type有很多种,对应 body 的格式也有区别。到底应该采用什么样的Content-Type取决于服务器端,所以请和服务器端的开发人员沟通确定清楚。常用的’Content-Type’除了上面的’application/json’,还有传统的网页表单形式,示例如下:

fetch('https://mywebsite.com/endpoint/', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded',
  },
  body: 'key1=value1&key2=value2',
})

可以参考Fetch 请求文档来查看所有可用的参数。

注意:使用 Chrome 调试目前无法观测到 React Native 中的网络请求,可以使用第三方的react-native-debugger来进行观测。

处理服务器的响应数据

网络请求天然是一种异步操作。Fetch 方法会返回一个Promise,这种模式可以简化异步风格的代码:

function getMoviesFromApiAsync() {
  return fetch('https://facebook.github.io/react-native/movies.json')
    .then((response) => response.json())
    .then((responseJson) => {
      return responseJson.movies;
    })
    .catch((error) => {
      console.error(error);
    });
}

你也可以在 React Native 应用中使用 ES2017 标准中的async/await 语法:

async function getMoviesFromApi() {
  try {
    let response = await fetch(
      'https://facebook.github.io/react-native/movies.json',
    );
    let responseJson = await response.json();
    return responseJson.movies;
  } catch (error) {
    console.error(error);
  }
}

默认情况下,iOS 会阻止所有 http 的请求,以督促开发者使用 https。如果你仍然需要使用 http 协议,那么首先需要添加一个 App Transport Security 的例外,详细可参考[这篇帖子](https://segmentfault.com/a/1190000002933776 这篇帖子)。

从 Android9 开始,也会默认阻止 http 请求,请参考[相关配置](https://blog.csdn.net/qq_40347548/article/details/86766932 相关配置)

;