为 JavaScript 程序员准备的 Flutter 指南

Flutter 是一款用同一套代码构建高性能、高保真的 iOS 及安卓应用的跨平台移动端应用 SDK。

文档中提到:

Flutter 包括一个 react 风格的框架、一个 2D 渲染引擎、一些预制的插件以及开发者工具。

upload successful

文本希望能快速为 JavaScript 开发者们提供一个简练的入门指南,我会试着以 JS 与 npm 生态系统来类比 Flutter / Dart 与 Pub 包库。

如果你对最新的 Flutter 教程、库、公告及社区的更新感兴趣,我建议您订阅双周刊 Flutter Newsletter


我在 React Native EU 的演讲 React Native — 跨平台及超越中讨论并演示了 React 生态系统中 React Native WebReact PrimitivesReactXP 的不同之处,并且我也有机会讨论 WeexFlutter 的不同之处。

在尝试 Flutter 之后,我认为它是近几年我所关注的前端技术中最让我激动的一个。在本文中,我将讨论为何它如此令我激动,并介绍如何尽可能快的入门 Flutter。

如果你认识我,那么我知道你正在想什么…

upload successful

我是一名有着超过两年半经验的 React 与 React Native 开发者。现在,我仍然看好 React 和 React Native,并且我也知道有许多大公司正在使用它们,但我仍然乐于看到其他的能达到相同目的的想法方法,这无关乎我是否要去学习或改变技术栈。

Flutter

我可以做个概括:Flutter 令人惊叹, 我相信近几年它会成为更多人的选择。

在使用了几周 Flutter SDK 之后,我正在应用它制作我的第一个 App,我十分享受这个过程。

在我开始介绍如何入门 Flutter 前,我将首先回顾一下我对它的 SDK 的优缺点的看法。

upload successful

优点

  • 内置由核心团队维护的 UI 库(Material 及 Cupertino)。
  • Dart 团队与 Flutter 团队紧密合作,专门针对 Flutter 优化移动设备的 Dart VM。
  • 有着崭新的、酷炫的文档。
  • 强大的 CLI。
  • 我能轻松、顺利地入门与运行它,没有碰到各种障碍与 Bug。
  • 开箱即用的热加载功能,使得调试的体验相当好。此外,还有一系列关于调试技术的很好的文档
  • 有由核心团队构建并维护的 nav 库,可靠且有见地。
  • Dart 语言诞生 6 年了,相当成熟。虽然 Dart 是一种基于类的面向对象编程语言,但如果你想用函数式编程,Dart 也有着作为第一公民的函数,并且支持许多函数式编程结构。
  • Dart 比我想象中的更容易入门,我十分喜欢它。
  • Dart 是一种无需任何多余配置的开箱即用的强类型语言(比如:TypeScript、Flow)。
  • 如果你用过 React,会发现它有类似的状态机制(比如 lifecycle 方法与 setState)。

缺点

  • 你要去学习 Dart(相信我,这很简单)。
  • 仍在测试中。
  • 目标平台仅为 iOS 和安卓。
  • 插件生态系统还很稚嫩,https://pub.dartlang.org/flutter 在 2017 年 9 月还只有 70 余个包。
  • 布局与编写样式需要学习一种全新的范式与 API。
  • 需要学习不一样的项目配置(pubspec.yaml vs package.json)。

入门及其它观点

  • Flutter 文档推荐了 VS Code 编辑器与 IntelliJ IDE。尽管 IntelliJ IDE 内置支持热加载、在线加载这些 VS Code 没有的功能,但我还是选择使用安装了 Dart Code extension 插件的 VS Code 编辑器,并得到了很好的开发体验。
  • Flutter 有一个模块系统,或者叫包管理系统 —— Pub Dart Package Manager,它与 npm 有很多不同点。它的好坏取决于你对 npm 的看法。
  • 我之前并没有 Dart 相关的知识,但我很快就入门了。它让我想起了 TypeScript,并且与 JavaScript 也有一些相似之处。
  • 文档中有几个相当不错的代码实验室与教程,建议去查阅一番:1. 构建 UIS 2. 增加 Firebase 3. 构建布局 4. 增加交互

说的够多了,现在让我们开始创建一个新的工程吧!

在 macOS 中安装 CLI

如果你使用的是 Windows,请查阅 此文档

如需查看完整的 macOS 平台下的安装指南,请查看 此文档

首先,我们需要克隆包含 flutter CLI 二进制文件的 repo,然后将其添加到系统目录中。比如我将 repo 克隆到了专门用于存放二进制文件的目录下,然后将这个新目录加到了 $HOME/.bashrc$HOME/.zshrc 文件中。

  1. 克隆 repo:
1
git clone -b alpha https://github.com/flutter/flutter.git
  1. 增加路径:
1
export PATH=$HOME/bin/flutter/bin:$PATH (或者填你选择的安装路径)
  1. 在命令行中运行 flutter doctor,检测 flutter 路径能被正确识别,并安装一切所需的依赖:
1
flutter doctor

安装其它依赖

如果你要部署 iOS app,那么必须安装 Xcode;如果你要部署安卓 app,那么必须要安装 Android Studio。

了解关于安装这两个不同平台的知识,请参阅文档文档

创建你的第一个 Flutter app

现在我们已经安装好了 flutter CLI,可以创建我们的第一个 app 了。请运行 flutter create 命令:

1
flutter create myapp

此命令会帮助你创建一个新的 app,进入新目录,打开 iOS 模拟器或安卓模拟器,运行以下命令:

1
flutter run

upload successful

此命令会在你打开的模拟器中运行 app。如果你同时打开了 iOS 与安卓模拟器,你可以用下面的命令来将程序传入指定的模拟器:

1
flutter run -d android / flutter run -d iPhone

也可以同时运行:

1
flutter run -d all

此时你应该在控制台中看到了关于重启 app 的信息:

upload successful

项目结构

你正在运行的代码处于 lib/main.dart 文件中。

你会发现有一个 andoird 文件夹和一个 iOS 文件夹,原生的项目存在这些目录中。

项目的配置在 pubspec.yaml 中,此文件与 JavaScript 生态系统中的 package.json 类似。

现在将目光转向 lib/main.dart

在文件的头部,可以看见一个 import:

import ‘package:flutter/material.dart’;

这个依赖文件是哪儿来的?请查看 pubspec.yaml 文件,可以发现在依赖列表中单独有一个 flutter 依赖项,在这儿是引用的 package:flutter/。如果想添加或导入其它依赖项,那么需要将新的依赖加入 pubspec.yaml,然后用过 import 来使用它们。

main.dart 的头部,我们还可以看到有一个名为 main 的函数。在 Dart 中,main 是一个特殊的、必要的、顶级的函数,也是 app 开始执行的地方。因为 Flutter 是由 Dart 构建的,main 也是这个工程的主入口。

1
2
3
void main() {
runApp(new MyApp());
}

此函数调用了 new MyApp(),这个类。与 React App 类似,有一个由多个组件组合而成的主组件,然后调用 ReactDOM.renderAppRegistry.registerComponent 进行渲染。

Widget

Flutter 技术总览中的一个核心原则就是:“一切皆 Widget”。

Widget 是每个 Flutter app 的最基本的构建模块。每个 Widget 都是用户界面的一个不可变定义。与其它框架分离视图、控制器、布局和其它属性不同,Flutter 有着统一的、一致的对象模型:Widget。

类比 Web 术语或 JavaScript,你可以将 Widget 看成与 Component 类似的东西。Widget 通常由内部类构成,这些类可能包含或不包含一些本地状态(local state)或方法。

如果你观察 main.dart,可以发现类似 StatelessWidget、StatefulWidget、Center、Text 的类引用。这些都是 Widget。如果想了解所有可用的 Widget,请查阅文档

布局与编写样式

虽然 Dart 和多数 Flutter 框架都很容易使用,但进行布局与编写样式让我最开始头疼了一阵子。

需要重点注意的是,与编写 Web 样式不同,以及与 React Native 的 View 会完成所有的布局和一些样式不同,Flutter 的布局由你选择的 Widget 类型本身的布局与样式属性共同决定,也就是说它通常取决于你使用的 Widget。

例如,Column 能接收多个子 Widget,但不接受任何样式属性(CrossAxisAlignmentdirection 等布局属性除外);而 Container 能接收各种布局及样式属性。

Flutter 还有一些布局专用的组件,比如 Padding,它仅能接收一个子 Widget,但除了给子 Widget 添加 padding(边距)之外不会做其它任何事。

请参考这个完整的 Widget 列表,能帮你使用 Container、Row、Column、Center、GridView 及其它有着自己布局规范的组件实现布局。

SetState 及生命周期函数

与 React 类似,Flutter 也有有状态、无状态组件或 Widget。有状态组件可以创建、更新、销毁状态,与 React 中使用的生命周期函数类似。

在 Flutter 中,也有一个名为 setState 的函数用来更新状态。你可以在我们刚才创建的项目的 _incrementCounter 方法中看到此函数。

更多信息请查阅:StatefulWidget, StateStatelessWidget

总结

作为专门制作跨平台应用的开发者,我会保持关注 React Native 的竞争对手。对于客户来说,也多了一种选择,他们可能会因为某些原因而要求使用 Fluter。我认为 Flutter 为我的客户带来了一些他们想要的东西,比如内置的类型系统、一流的 UI 库、由核心团队维护的 nav 库等。

我会把 Flutter 加入我的技术栈中,当碰到 React Native 无法解决的问题和情况时,我将会使用 Flutter。只要我觉得可以将它用于生产环境,我会向客户展示我的第一个 Flutter app,供他们选择这个技术。

掘金链接:https://juejin.im/post/5ac43c536fb9a028da7cbd59