微信号:frontshow

介绍:InfoQ大前端技术社群:囊括前端、移动、Node全栈一线技术,紧跟业界发展步伐。

我们用Flutter重写了一个React Native应用

2018-08-19 14:51 无明 译
作者|GeekyAnts
译者|无明
编辑|覃云

去年,我们推出了一个名为 Flat App 的 React Native 入门套件。这个套件包含了一个扁平风格的 UI 设计和适用于 iOS 和 Android 的 Redux 和 NativeBase 组件。Flat App 基本上算是一种界面设计风格,旨在减少对风格元素的使用。众所周知,开发人员更喜欢扁平设计,因为它可以让界面设计变得更简单和高效。作为一项实验,我们使用谷歌的 Flutter 成功地重写了这个应用,结果真的很棒。

在这篇文章中,我将从语言栈、UI、样式和其他方面对 Flutter 和 React Native 进行比较。同时,我还将讨论在重写 Flat App 过程中遇到的一些挑战,以及我们是怎样解决的。

试水 Flutter

Flutter 是一个由谷歌构建的平台,帮助我们快速构建可以在 Android 和 iOS 平台上运行的应用程序。

Flutter 与众不同的地方是它有一个 C/C++ 层,但系统的大部分都是用 Dart 实现的,开发人员可以轻松地进行读取、替换或移除。这为开发人员提供了灵活的系统控制。

语言栈

React Native 是一个 JavaScript 库,但 Flutter 却是一个 SDK,它使用的是一门名为 Dart 的编程语言。

  JavaScript

虽然 JavaScript 最初是为 Web 开发而生,但到了今天,JavaScript 生态系统已经变得如此庞大,以至于很多地方都能看到它的身影。

React Native 在运行时将动态 JavaScript 代码编译为原生视图,其余代码则通过嵌在应用程序内部的虚拟机来运行。

  Dart

Dart 是一门由谷歌开发的通用编程语言。它还可用于构建 Web、服务器端、移动端和物联网设备应用程序。

Dart 受到很多编程语言的影响,其中对它影响最大的是 Java。Java 程序员应该很容易看出这两种语言之间的相似之处。

Dart 是一种面向对象的编程语言,支持抽象、封装、继承和多态等特性。

Dart 程序可以在以下两种模式下运行:

  • 在 checked 模式下,它将启用动态类型断言。如果代码中包含了静态类型,那么可以打开类型断言。在开发和测试时建议使用 Checked 模式,因为它有助于在类型不匹配时捕获代码中的错误。

  • 生产模式是 Dart 程序的默认模式。它提供了一种更快的方式来运行程序。

Dart 示例:

int fib(int n) => (n > 2) ? (fib(n - 1) + fib(n - 2)) : 1;

void main() {
  print('fib(20) = ${fib(20)}');
}

尽管 Dart 拥有强大的社区影响力,但仍然被其他主流语言(如 JavaScript)占了上风,因此很少有开发者了解 Dart。

但这种情况正在发生改变。感谢 Flutter 发布了 Beta 1!在我撰写这篇文章时,Flutter 的 GitHub 代码库(https://github.com/flutter/flutter)已经获得了 18000 个 star!

Flutter 有一个函数反应式框架,主要是受 React 的启发。虽然 Flutter 是用 Dart 编写的,但它也借鉴了 React 的一些最好的特性,帮助开发人员构建出漂亮的跨平台移动应用程序。

样式
  React Native

在 React Native 中,样式是通过 JavaScript 来定义的。React Native 的所有核心组件都接受名为 style 的 prop。样式名称和值通常与 Web 中的 CSS 类似。唯一的区别是,在 React Native 中,名称采用了驼峰的格式。因此,要定义背景颜色,需要将样式命名为 backgroundColor,而不是 background-color。

如果我们使用 StyleSheet.create 在一个地方定义多个样式,代码就会变得更清晰。随着应用程序变得越来越复杂,这种方式会非常有用。

  Flutter

样式的差异在 Flutter 中比在 React Native 中表现得更为明显。这个从下面给出的例子就可以看出来。

这是一段 React Native 代码,用于定义字体样式和其他文本属性。

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

export default class LotsOfStyles extends Component {
  render() {
    return (
      <View style={styles.greybox}>
        <Text>Lorem Ipsum</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  greybox: {
    backgroundColor: #e0e0e0,
    width: 320px;
    height: 240px;
    font: 900 24px Georgia;
  }
})

// skip this line if using Create React Native App
AppRegistry.registerComponent('AwesomeProject', () => LotsOfStyles);

如果我们想要在 Flutter 中实现同样的样式,那么可以写成:

var container = new Container( // grey box
  child: new Text(
    "Lorem ipsum",
    style: new TextStyle(
      fontSize: 24.0
      fontWeight: FontWeight.w900,
      fontFamily: "Georgia",
    ),
  ),
  width: 320.0,
  height: 240.0,
  color: Colors.grey[300],
);
架构
  React Native

React Native 应用程序的架构被称为 Flux。Facebook 使用 Flux 构建客户端 Web 应用程序。Flux 使用的是单向数据流。Flux 更像是一种模式,而不是一种正式的框架。任何人都可以轻松使用 Flux,而无需编写大量新代码。

单向数据流是 Flux 的主要概念。

Dispatcher、Store 和 View 是具有不同输入和输出的独立节点。Action 是包含新数据和 type 属性的简单对象。View 可能会产生新的操作,并通过系统传播,以便对用户交互做出响应。

  Flutter

Flutter 有一个名为 Flutter Flux 的 Dart 库。它是一种单向数据流,受到 RefluxJS 和 Facebook Flux 的启发。

Flutter Flux 不受 Flutter 团队的官方支持,只是一个实验性的软件包。

Flutter Flux 几乎与 React/React Native 的实现是一样的,只是使用 Flutter 替换了 React。

Flutter Flux 实现了单向数据流模式,由 Action、Store 和 StoreWatcher 组成。

Action 修改保存在 Store 中的数据。Store 的数据被修改时会触发 View 进行重新渲染。

Flutter Widget 和其他交互源通过调用 Action 对用户的输入做出响应。

用户界面
  React Native

使用 React Native 就像使用不包含 CSS 框架的 HTML 一样。

与 Flutter 版本的 Flat App 不同,在使用 React Native 时,我们必须使用第三方库,因为 React Native 没有自己的 UI 组件库。

我们使用了 NativeBase 等组件,它是我们自己创建的开源 UI 组件库。React Native Elements、React Native Material Design 和 Shoutem 是其他可以考虑使用的 UI 库。

  Flutter

Flutter 提供了自己的 UI 组件,以及在 Android 和 iOS 平台上渲染组件的引擎。其中大部分组件符合 Material Design 风格。

我们正在使用 Flutter 的内置组件来开发应用程序的 UI。这些组件称为小部件。我们只需使用正确的小部件,并将正确的 prop 传给小部件,就可以获得我们想要的 UI。

Flutter 中的每个小部件都有它们自己的属性定义,并且可以嵌套在其他小部件中。窗口小部件还可以调用父部件的属性。

Flutter 版本的 Flat App 比 React Native 更好,因为它与原生代码的交互最少。这也是为什么 Flutter 版的 Flat App 的动画会运行得更快。

在 React Native 中,我们也可以桥接原生模块和使用原生 UI 组件。但这在 Flutter 中是不可能的,因为 Flutter 有自己的渲染引擎。

这实际上也是 Flutter 尚未支持谷歌地图的原因。

以下是 Flutter Widget 的几个示例:

  Drawer

Drawer 是一种 Material Design 面板,可从 Scaffold 边缘水平滑动出来,上面显示应用程序的导航链接。下面分别是 Flutter 版 Flat App 的 Drawer 的代码和 React Native 版的代码(SideBar):

  Inkwell

Inkwell 定义了一个 Material 矩形区域,可对触摸做出响应。我们使用这个小部件创建涟漪效果,当用户触摸这个区域时就会出现波纹效果。

在 React Native 中,我们不需要创建一个全新的组件来实现这种涟漪效果。React Native 的 TouchableOpacity 已默认具有这样的效果。

  GestureDetector

顾名思义,GestureDetector 是一个用于检测手势的小部件。GestureDetector 会尝试识别与非空回调相对应的手势。

如果这个小部件有子部件,就会根据子部件调整大小。如果没有子部件,就会根据父部件调整大小。

如下面的代码所示,GestureDetector 小部件将根据 Container 小部件调整大小。

GestureDetector 相当于 React Native 中的 TouchableOpacity。因此,我们不需要为它创建新的部件。

  DefaultTabController

DefaultTabController 是默认的 TabController 小部件,在没有明确指定小部件时会用到。

DefaultTabController 用于与 TabBar 或 TabBarView 共享 TabController。我们使用这个小部件与 TabBar 共享 TabController。

当不方便共享显式创建的 TabController 时就可以使用这个小部件,因为 TabBar 小部件是由无状态父部件或不同的小部件创建的。

在 React Native 版的 Flat App 中,我们使用 Tab Navigator 执行相同的操作。

  插 件  
  React Native

React Native 背后有一个庞大的社区在支持。

这也是为什么 React Native 拥有比 Flutter 更多的第三方库和插件。

在 React Native 版的 Flat App 中,我们使用了很多不同的第三方库,例如 Calendar、Carousel 和 Modal。

  Flutter

我们将 Flutter 版的 Flat App 与 Firebase 集成在一起来实现登录和注册功能。

在 Flutter 中,我们需要为 iOS 和 Android 平台添加单独的文件。在每个文件中,我们需要添加与平台规则相关的代码。

与 Flutter 应用中使用 Firebase 不是件简单的事。请查看谷歌提供的演示(https://codelabs.developers.google.com/codelabs/flutter-firebase/),了解如何将 Firebase 添加到 Flutter 应用中。

为 Flutter 构建新的插件也很容易,几乎每隔一天就会出现新的 Flutter 插件。

社区
  React Native

React Native 是由 Facebook 和 Instagram 的工程师于 2015 年创建的。从那时起,他们的十几名工程师一直在全职开发 React Native,他们精益求精,希望帮助用户解决他们面临的所有问题。

不过,社区中也有很多人为这个项目做出了重要贡献并解决了很多问题。

你通常可以在 React Native 文档和指南中找到大多数问题的解决方案,或者可以在 StackOverflow 和 GitHub 上与其他 React Native 开发人员取得联系,你可以在上面展示你的项目或向其他开发人员寻求指导。

如果你想成为贡献者,请先阅读贡献者指南和路线图,以便了解其他人正在开展的工作。你还可以查看由社区提出的最常用的功能清单。

  Flutter

Flutter 的文档非常全面,可以帮助你入门 Flutter 开发。

Flutter Gallery(https://github.com/flutter/flutter/tree/master/examples/flutter_gallery)展示了所有可用的 Flutter 组件。我们也可以参看 Flutter 的 GitHub 代码库,了解它的实现。

Flutter 社区并不像 React Native 那样强大。但是,谷歌 Flutter 团队为此提供了非常好的支持。他们提供了很多方式来收集我们的问题,并在合理的时间内解决这些问题。

问题
  React Native

虽然 React Native 是一个单独的代码库(JavaScript),但它的 View 组件在 iOS 上的行为与在 Android 上的行为不一样。

尽管 React Native 的广大社区可以为我们提供很多不同的插件和库,但也可能导致与现有项目的其他插件发生冲突。

  Flutter

如果你有使用 JSX 的经验,那么编写 Flutter 的 UI 代码对你来说可能有点乏味。随着 UI 变得越来越复杂,代码可读性也会随之下降。

一种解决方案是将代码重构为方法和小部件。我们目前正在尝试这种方法,看看它是否会让 build() 方法变得更容易阅读。

在 Flutter 中,没有必要将代码都放在 build() 方法中。相反,你可以把它分解成更小的小部件!

与 React Native 相比,Flutter 的资源确实有点匮乏。其中一个重要的原因是 Flutter 存在的时间没有 React Native 那么长。但自从 Beta 版本发布以来,Flutter 的资源有了巨大的增长。

总结

Flutter 的一个主要好处是它提供了内置的 UI 组件,因此我们不需要导入第三方 UI 库。通过减少原生层和运行时环境之间的交互,Flutter 让应用程序可以更平稳更快地运行。

Flutter 刚进入 Beta 阶段,但已经有不少开发人员使用它构建应用程序。Flutter 还有很长的路要走。谷歌的 Flutter 团队正在全力以赴,将 Flutter 带给广大开发者。

  英文原文

https://blog.geekyants.com/we-rebuilt-a-react-native-app-with-flutter-4160f0499a82

  课程推荐

推荐极客时间《技术管理实战 36 讲》专栏,前百度最佳经理人刘建国为你解惑团队 leader 的 36 个场景,传授打造高效团队的 13 种方法,分享十年管理的“战地笔记”。

现在订阅,立享限时福利:

福利一:限时优惠价¥45,原价¥68,8 月 25 日恢复原价

福利二:每邀请一位好友购买,你可获得 12 元现金返现,好友可返 6 元。多邀多得,上不封顶,随时提现(提现流程:极客时间 App - 我的 - 分享有赏)

阅读原文,免费试读或订阅!


 
前端之巅 更多文章 专访尤雨溪:先别管4.0了,Vue CLI重构了解一下 用实例告诉你如何重构带有坏味道的代码 Web性能分析工具WebpageTest详解 谷歌推出最新AngularJS升级工具,可快速迁移至Angular 在开始React之前,你需要学好这些JavaScript
猜您喜欢 移动端导航模式的热门设计 iPhone X未能幸免,以色列公司发现解锁任意iPhone设备的方法 【测试漫谈】基于GUI的自动化测试框架漫谈 【02-11】 分享下从开发上线的操作流程、辅助工具等 【黑帽官方】 2016独家黑帽网SEO培训从零开始(第四期)