React Native 入门教程:基础知识与使用指南

Viewed 0

React Native 基础知识及入门使用

起步

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

如果你是移动开发新手,最简单的入门方法是使用 Expo CLI。Expo 是一套围绕 React Native 构建的工具,最基础的功能是让你在几分钟内编写一个 React Native 应用程序。你只需要 Node.js 的最新版本和一个手机或模拟器。如果您想在安装任何工具之前直接在 web 浏览器中试用 React Native,可以试用 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 客户端应用程序,并连接到与计算机相同的无线网络。在 Android 上,使用 Expo 应用程序从终端扫描二维码以打开项目。在 iOS 上,按照屏幕上的说明(一般为使用相机扫描)获取链接。

修改你的程序

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

基础知识

React Native 与 React 类似,但它使用原生组件而不是基于浏览器组件作为构建块。因此,要了解 React Native 应用程序的基本结构,您需要了解一些基本的 React 概念,如 JSX、组件、状态和属性。如果你已经了解 React,那么你仍然需要学习一些 React 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 文件中,以便在本地计算机上创建真正的原生应用程序。

JSX 语法

首先,ES2015(也称为 ES6)是对 JavaScript 的一系列改进,现在是官方标准的一部分。React Native 支持 ES2015,因此你可以使用这些内容而不必担心兼容性。上述示例中的 import、from、class 和 extends 都是 ES2015 的特性。

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

组件

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

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('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 的例外,详细可参考相关文档。

从 Android 9 开始,也会默认阻止 http 请求,请参考相关配置。

0 Answers