使用 React Native Web 构建适合移动设备的 Web 应用程序

介绍

多年来,随着媒体查询的出现和服务工作者的引入,构建对移动友好的 Web 应用程序变得更加容易。使用媒体查询,我们可以支持不同移动设备的屏幕尺寸。使用 Service Worker,我们可以实现推送通知和后台同步等功能。

React Native是由 Facebook 开发的多平台解决方案,可让您使用 JavaScript 构建移动应用程序。这些移动应用程序被认为是多平台的,因为它们编写一次并部署在多个平台上,例如 Android、iOS 和 Web。

在本教程中,您将使用 React Native 组件(如和 )构建一个应用程序,该应用程序显示来自Random User API 的用户信息该应用程序将使用React Native Web在 Web 和移动设备上运行,它允许您在 Web 应用程序中使用 React Native 组件和 API。ScrollViewTextImage

注意:本教程末尾记录的部署过程是特定于 Android 的。然而,对于那些对 iOS 部署感兴趣的人来说,这个过程可能仍然具有教育意义。

先决条件

要完成本教程,您需要:

本教程最初是在 Node v10 时编写的。当时,依赖项包括reactv16.6.3、react-nativev0.9.8 和expov31.0.5。

本教程已通过 Node v14.2.0、npmv6.14.5、16.13.1、reactv0.62.2react-nativeexpov37.0.11 验证。

步骤 1 — 设置项目

在开始之前,您需要设置项目并安装项目依赖项。

您将使用Create React App来引导您的应用程序。您正在使用 Create React App,因为它可以配置为 React Native 的别名。

要使用 Create React App 引导您的应用程序,请在终端中运行以下命令:

  • npx create-react-app random-people

注意:本教程采用采用现有 React 应用程序并将其转换为 React Native 的方法。另一种等效方法是使用npx react-native init.

导航到您的新项目目录:

  • cd random-people

你会为一些最新的JavaScript API等来安装polyfills PromiseArray.from等等,因为transpiler不提供这些。

运行以下命令安装项目的开发依赖:

  • npm install --save-dev babel-plugin-module-resolver@4.0.0 babel-plugin-transform-object-rest-spread@6.26.0 babel-plugin-transform-react-jsx-source@6.22.0 babel-preset-expo@8.1.0

babel-plugin-module-resolver是一个在使用 Babel 编译时解析您的项目模块的插件。您将使用这个包的别名react-native,以react-native-web建立项目配置的时候。

我们将使用Expo来构建和运行新的应用程序。Expo 是一个围绕 React Native 构建的开源工具链,用于构建 Android 和 iOS 应用程序。它提供对系统功能的访问,如相机和存储。

注意:如果您有兴趣稍后部署您的应用程序,您将需要一个 Expo 帐户。

首先,在全球安装 Expo CLI:

  • npm install --global expo-cli@3.25.1

接下来,在本地安装 Expo:

  • npm install expo@37.0.0

然后,安装 React Native 和 React Native Web:

  • npm install react-native@0.62.2 react-native-web@0.12.2 react-art@16.13.1

下载运行和构建应用程序所需的包后,下一步是设置配置文件。创建一个.babelrc在项目根目录中调用的文件

  • nano .bablerc

将以下代码添加到文件中以配置您的项目将使用的转译器:

.babelrc
{
  "presets": ["babel-preset-expo"],
  "env": {
    "development": {
      "plugins": [
        "transform-object-rest-spread",
        "transform-react-jsx-source"
      ]
    }
  },
  "plugins": [
    [
      "module-resolver",
      {
        "alias": {
          "^react-native$": "react-native-web"
        }
      }
    ]
  ]
}

创建一个名为 的文件app.json

  • nano app.json

此文件用于应用程序的配置部分不代码属于,像应用程序namedescriptionsdkVersion等,您可以找到可用的选项app.json文件世博文档中

添加以下代码行:

应用程序.json
{
  "expo": {
    "sdkVersion": "37.0.0",
    "name": "random-people",
    "slug": "random-people",
    "version": "0.1.0",
    "description": "An application for displaying random people",
    "primaryColor": "#ff8179"
  }
}

注意:在测试本教程时,最新的 Expo SDK 版本为 37。稍后,您可能需要运行expo upgrade(或手动修改您的app.jsonpackage.json文件并运行npm install)。参阅 Expo 文档以升级 SDK

让我们更新package.json文件以包含在 Android 和 iOS 模拟器上运行应用程序的命令。此外,您将包括main引用App.js文件字段该文件将作为expo-cli. package.json在编辑器中打开文件:

  • nano package.json

修改文件,使其看起来像这样:

包.json
{
    "name": "random-people",
    "version": "0.1.0",
    "private": true,
    "main": "./App.js",
    // ...
    "scripts": {
        "start-web": "react-scripts start",
        "build-web": "react-scripts build",
        "test-web": "react-scripts test",
        "eject-web": "react-scripts eject",
        "start-native" : "expo start",
        "android": "expo start --android",
        "ios": "expo start --ios",
        "build:ios": "expo build:ios",
        "build:android": "expo build:android"
    },
    // ...
}

运行npm run start-web以运行应用程序并localhost:3000在 Web 浏览器中访问以查看应用程序。

第 2 步 – 创建Home组件

您的应用程序将通过 Random User API 显示用户。使用 API,您将收到返回用户的显示名称和头像。

src目录中,创建一个名为 的文件home.js

  • nano src/home.js

将此代码添加到文件以定义组件:

源代码/home.js
import React from "react";
import { ScrollView, ActivityIndicator, StyleSheet } from "react-native";

class Home extends React.Component {
  state = {
    users: [],
    loading: true
  };

  componentDidMount() {
    // TODO: get users
  }

  render() {
    return (
      <ScrollView
        noSpacer={true}
        noScroll={true}
        style={styles.container}
      >
       <ActivityIndicator
            style={[styles.centering, styles.gray]}
            color="#ff8179"
            size="large"
          />
      </ScrollView>
    );
  }
}

var styles = StyleSheet.create({
  container: {
    backgroundColor: "whitesmoke"
  },
  centering: {
    alignItems: "center",
    justifyContent: "center",
    padding: 8,
    height: '100vh'
  },
});

export default Home;

Home组件呈现一个包含组件元素ScrollView组件。

目前,该组件显示一个ActivityIndi​​cator当对 API 的调用完成时,这将被用户列表替换。

您将使用StyleSheet组件为元素创建样式这允许您使用类似于 CSS 属性的属性来设置组件的样式。

让我们创建一个从 Random User API 获取随机用户的方法。该方法将在componentDidMount生命周期中被调用

更新home.js组件以包含该getUsers方法:

源代码/home.js
// ...

class Home extends React.Component {
  state = {
    // ...
  };

  componentDidMount() {
    this.getUsers();
  }

  async getUsers() {
    const res = await fetch("https://randomuser.me/api/?results=20");
    const { results } = await res.json();
    this.setState({ users: [...results], loading: false });
  }

  render() {
    // ...
  }
}

// ...

您可以使用本机FetchAPI轻松发出请求请求的结果被解析并添加到状态。请求完成后,您将ActivityIncidator通过设置loading为 false 来隐藏

第 3 步 – 创建App组件

AppComponent适用于该应用程序的逻辑。您将通过添加显示本机组件的逻辑来更新 Create React App 创建的默认视图,以适应您的应用程序的视图。

替换src/App.js文件内容

应用程序.js
import React from 'react';
import { AppRegistry, StyleSheet, View } from 'react-native';
import Home from './home';

class App extends React.Component {
  render() {
    return (
      <View style={styles.appContainer}>
        <Home />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  appContainer: {
    flex: 1,
  },
});

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

export default App;

在上面的代码段中,您<App>使用AppRegistry. AppRegistry是切入点的阵营本地应用程序。

此版本App.js显示网页版。您将需要一秒钟App.js来显示 React Native 版本。

在项目的根目录中复制src/App.js一个新App.js文件:

  • cp src/App.js App.js

注意:请务必App.js使用这些更改来修改项目根目录中文件,以便在测试时与 Expo 一起使用。

更改 的路径很重要Home./home./src/home

现在,您将创建<UserItem>组件。

第 4 步 – 创建 UserItem

每个用户项目将使用一个View组件显示视图组件是一个重要组成部分,它支持使用Flexbox的,造型和可访问的布局。View每个项目组件将在一个SwipeableFlatList. 每个项目将显示用户的头像、姓名和电子邮件。

创建一个user-item.jssrc目录中调用文件:

  • nano src/user-item.js

将以下代码添加到文件中:

用户项.js
import React from "react";
import { View, Image, Text, StyleSheet } from "react-native";

const UserItem = ({ item: user }) => {
  return (
    <View style={styles.row}>
      <Image style={styles.rowIcon} source={user.picture.medium} />
      <View style={styles.rowData}>
        <Text style={styles.rowDataText}>
          {`
            ${user.name.title}
            ${user.name.first}
            ${user.name.last}
          `}
        </Text>
        <Text style={styles.rowDataSubText}>{user.email}</Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  row: {
    flexDirection: "row",
    justifyContent: "center",
    alignItems: "center",
    padding: 15,
    marginBottom: 5,
    backgroundColor: "white",
    borderBottomWidth: StyleSheet.hairlineWidth,
    borderBottomColor: "rgba(0,0,0,0.1)"
  },
  rowIcon: {
    width: 64,
    height: 64,
    marginRight: 20,
    borderRadius: "50%",
    boxShadow: "0 1px 2px 0 rgba(0,0,0,0.1)"
  },
  rowData: {
    flex: 1
  },
  rowDataText: {
    fontSize: 15,
    textTransform: "capitalize",
    color: "#4b4b4b"
  },
  rowDataSubText: {
    fontSize: 13,
    opacity: 0.8,
    color: "#a8a689",
    marginTop: 4
  }
});

export default UserItem;

要显示每个用户的头像,您可以使用Image组件。该组件采用一个source道具,它可以src作为您在网络上使用道具您可以使用styles.rowIcon属性进一步设置组件的样式

接下来,您将创建UserList以显示每个UserItem.

第 5 步 — 创建 UserList

FlatList组件是一种在其列表呈现方法中性能良好组件。它延迟加载列表中的项目,并且仅在用户滚动到列表底部时加载更多项目。TheSwipeableFlatListFlatListReact Native Web 提供的包装器,它使列表中的每个项目都可以滑动——因此每个项目在滑动时都会显示一组操作。

SwipeableFlatList以前是 的一部分react-native,但此后已被删除要使用它,请安装以下软件包:

  • npm install react-native-swipeable-lists@0.0.1

注意:或者,还有其他SwipeableFlatList可用的实现

让我们SwipeableFlatList为从 API 返回的用户创建SwipeableFlatListreact-native-swipeable-lists包中导入组件并更新渲染函数以显示列表。user-list.jssrc目录中创建一个名为文件:

  • nano src/user-list.js

将此代码添加到文件中:

源代码/用户列表.js
import React from "react";
import { SwipeableFlatList } from "react-native-swipeable-lists";
import UserItem from "./user-item";

const UserList = ({ users }) => {
  return (
    <SwipeableFlatList
      data={users}
      bounceFirstRowOnMount={true}
      maxSwipeDistance={160}
      renderItem={UserItem}
    />
  );
};

export default UserList;
  • data:这个道具代表将被馈送到列表中每个项目的数据。所述data支柱通常是一个数组。
  • bounceFirstRowOnMount: 如果为 true,它会在列表中的第一个项目上触发反弹动画,表示它有隐藏的动作。
  • maxSwipeDistance:此道具为每个项目设置最大可滑动距离。
  • renderItem:这个道具接受一个渲染项目的函数;此函数将传递一个item包含要显示的数据道具。

注意:或者,还有其他SwipeableFlatList可用的实现

让我们更新src/home.js文件以包含新的UserList.

打开src/home.js文件:

  • nano src/home.js

并使用以下内容更新它:

源代码/home.js
import React from "react";
import { ScrollView, ActivityIndicator, StyleSheet } from "react-native";
import UserList from "./user-list";

class Home extends React.Component {
  state = {
    // ...
  };

  componentDidMount() {
    // ...
  }

  render() {
    return (
      <ScrollView
        noSpacer={true}
        noScroll={true}
        style={styles.container}
      >
        {this.state.loading ? (
          <ActivityIndicator
            style={[styles.centering, styles.gray]}
            color="#ff8179"
            size="large"
          />
        ) : (
          <UserList users={this.state.users} />
        )}
      </ScrollView>
    );
  }
}

// ...

export default Home;

现在,如果您localhost:3000在浏览器上访问,您将看到一个用户列表。

您添加了一个SwipeableFlatList组件,这意味着每个用户项目都是可滑动的。接下来,添加用户可以滑动以显示的操作。

第 6 步 – 向项目添加操作

列表中的每个项目都将提供一组操作,当向左滑动时将显示这些操作。操作集将使用TouchableHighlightView 组件包含的组件。TouchableHighlight当你需要观众来接触,或多或少表现得像一个按钮响应组件使用。

user-actions.jssrc目录中创建一个名为文件:

  • nano src/user-actions.js

将以下内容添加到文件中:

源代码/用户操作.js
import React from "react";
import { View, TouchableHighlight, Text, Alert, StyleSheet } from "react-native";

const UserActions = () => {
  return (
    <View style={styles.actionsContainer}>
      <TouchableHighlight
        style={styles.actionButton}
        onPress={() => {
          Alert.alert("Tips", "You could do something with this edit action!");
        }}
      >
        <Text style={styles.actionButtonText}>Edit</Text>
      </TouchableHighlight>
      <TouchableHighlight
        style={[styles.actionButton, styles.actionButtonDestructive]}
        onPress={() => {
          Alert.alert(
            "Tips",
            "You could do something with this remove action!"
          );
        }}
      >
        <Text style={styles.actionButtonText}>Remove</Text>
      </TouchableHighlight>
    </View>
  );
};

const styles = StyleSheet.create({
  actionsContainer: {
    flex: 1,
    flexDirection: "row",
    justifyContent: "flex-end",
    alignItems: "center",
    padding: 10
  },
  actionButton: {
    padding: 10,
    color: "white",
    borderRadius: 6,
    width: 80,
    backgroundColor: "#808080",
    marginRight: 5,
    marginLeft: 5
  },
  actionButtonDestructive: {
    backgroundColor: "#ff4b21"
  },
  actionButtonText: {
    textAlign: "center"
  }
});

export default UserActions;

TouchableHighlight组件采用onPress在单击该组件时触发回调。每个回调都会触发一次Alert显示。样式也应用于包含视图组件和页面上的其他组件。

要包含对每个用户项的操作,请更新UserList组件以包含renderQuickActionsprop,它也带有一个函数。

打开src/user-list.js并修改它:

源代码/用户列表.js
// ...

import UserActions from "./user-actions";

const UserList = ({ users }) => {
  return (
    <SwipeableFlatList
      // ...
      renderQuickActions={UserActions}
    />
  );
};

export default UserList;

现在,当您在任何用户项上向左滑动时,它会显示两个操作 –EditRemove

第 7 步 – 添加Header组件

现在您已成功获取用户并使用本机组件显示它们,让我们添加一个标题。使用该SafeAreaView组件,您将创建一个具有定义边界的区域。这将作为您的应用程序的标头。

header.jssrc目录中创建一个名为的新文件

  • nano src/header.js

将以下代码添加到文件中:

src/header.js
import React from 'react';
import { SafeAreaView, View, Text, StyleSheet } from 'react-native';

const Header = ({ onBack, title }) => (
  <SafeAreaView style={styles.headerContainer}>
    <View style={styles.header}>
      <View style={styles.headerCenter}>
        <Text accessibilityRole="heading" aria-level="3" style={styles.title}>{title}</Text>
      </View>
    </View>
  </SafeAreaView>
);

const styles = StyleSheet.create({
  headerContainer: {
    borderBottomWidth: StyleSheet.hairlineWidth,
    borderBottomColor: '#ff4e3f',
    backgroundColor: '#ff8179',
  },
  header: {
    padding: 10,
    paddingVertical: 5,
    alignItems: 'center',
    flexDirection: 'row',
    minHeight: 50
  },
  headerCenter: {
    flex: 1,
    order: 2
  },
  headerLeft: {
    order: 1,
    width: 80
  },
  headerRight: {
    order: 3,
    width: 80
  },
  title: {
    fontSize: 19,
    fontWeight: '600',
    textAlign: 'center',
    color: 'white'
  },
});

export default Header;

现在,让我们将Header组件添加App组件中。这将在应用程序顶部显示一个简单的标题。

更新App.js文件以包含Header组件:

源代码/App.js
// ...

import Header from './header';

class App extends React.Component {
  render() {
    return (
      <View style={styles.appContainer}>
        <Header title="Random People" />
        <Home />
      </View>
    );
  }
}

// ...

export default App;

应用程序刷新后,标题将添加到应用程序的顶部。

注意:请务必App.js使用这些更改来修改项目根目录中文件,以便在测试时与 Expo 一起使用。

更改 的路径很重要Header./header./src/header

让我们看看可用于在移动设备上测试应用程序的各种方法。

第 8 步 — 在移动设备上进行测试

expo-cli实用程序提供了各种方法来测试移动设备上的应用程序。第一种是使用运行应用程序后生成的 URL。您可以在移动浏览器上访问此 URL 来测试应用程序。

为了在移动设备上测试应用程序,expo-cli提供了各种方法来测试移动应用程序。第一种是使用运行应用程序后生成的 URL。可以在您的移动浏览器上访问此 URL 以测试应用程序。

在您的项目中运行以下命令以使用 Expo 运行应用程序:

  • npm run start-native

Expo 通常在 port 上启动您的应用程序19002,因此请访问localhost:19002以查看 Expo 开发工具。在开发工具中,您可以将链接作为短信或电子邮件发送到您的手机。

您可以选择三个连接选项中的任何一个 — 外部隧道、LAN 或本地连接。对于本地连接,您的手机和开发计算机必须连接到同一网络,但无论如何隧道都可以工作。

在移动设备上进行测试的下一个选项是使用模拟器。使用Android studioXcode,您可以为各自的平台启动模拟器。下载并安装适用于所选平台的工具——适用于 iOS 的 Xcode 或适用于 Android 的 Android Studio。

安装后,在任何模拟器上运行npm run androidnpm run ios启动应用程序。

步骤 9 — 部署应用程序

注意:这是完成本教程不需要的可选步骤。对于从项目创建到应用商店提交的工作流程的教育目的,应该考虑这一点。

您将把应用程序部署到 Android Play 商店。为此,您需要更新app.json文件以包含Android特定属性。打开app.json文件并更新文件以包含该android字段:

应用程序.json
{
  "expo": {
    "sdkVersion": "37.0.0",
    "name": "random-people",
    "slug": "random-people",
    "version": "0.1.0",
    "description": "An application for displaying random people",
    "primaryColor": "#ff8179",
    "android": {
      "package": "com.random.people"
    }
  }
}

android.package字段是一个唯一值,将代表您在应用商店中的包。您可以在此处阅读有关包命名约定的更多信息

更新文件后,运行npm run build:android命令。

此命令将向您显示一个提示,要求您提供一个密钥库或生成一个新密钥库如果您有现有的密钥库,您可以选择此选项或让 expo 为您的应用程序生成一个。

完成后,将为您的应用程序生成一个下载链接。单击此链接将触发下载您的 APK。

要将下载的 APK 部署到 Android Play 商店,请访问Play 管理中心创建一个帐户。创建帐户后,您需要支付 25 美元的注册费才能继续。完成注册过程后,请访问此页面并按照步骤将您的应用程序上传到 Play 商店。

结论

使用 React Native Web 和 React Native 库,您创建了一个可以使用本机组件部署在多个平台上的应用程序。构建多平台应用程序从未如此简单。

您可以在 GitHub 上查看演示的源代码

如果您想了解有关 React 的更多信息,请查看我们的How To Code in React.js系列,或查看我们的 React 主题页面以获取练习和编程项目。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁