跳到主内容

声明式 UI 简介

解释了声明式和命令式编程风格之间的区别。

本简介描述了 Flutter 使用的声明式风格与许多其他 UI 框架使用的命令式风格之间的概念性差异。

为什么选择声明式 UI?

#

从 Win32 到 Web,再到 Android 和 iOS 的框架通常使用命令式 UI 编程风格。 这可能是你最熟悉的风格——你手动构建一个功能齐全的 UI 实体,例如 UIView 或等效对象,然后在 UI 更改时使用方法和 setter 对其进行修改。

为了减轻开发人员编程 UI 状态转换的负担,Flutter 相反地让开发人员描述当前的 UI 状态,并将状态转换交给框架处理。

然而,这需要对如何操作 UI 进行略微的思维转变。

如何在声明式框架中更改 UI

#

考虑以下简化示例

View B (contained by view A) morphs from containing two views, c1 and c2, to containing only view c3.

在命令式风格中,你通常会访问 ViewB 的所有者并使用选择器或 `findViewById` 或类似方法检索实例 `b`,并在其上调用修改方法(并隐式使其失效)。 例如

java
// Imperative style
b.setColor(red)
b.clearChildren()
ViewC c3 = new ViewC(...)
b.add(c3)

你可能还需要在 ViewB 的构造函数中复制此配置,因为 UI 的真相来源可能比实例 `b` 本身更长寿。

在声明式风格中,视图配置(例如 Flutter 的 Widgets)是不可变的,并且只是轻量级的“蓝图”。 要更改 UI,一个 Widget 会在其自身上触发重建(最常见的是在 Flutter 中调用 StatefulWidgets 上的 `setState()`),并构建一个新的 Widget 子树。

dart
// Declarative style
return ViewB(color: red, child: const ViewC());

在这里,Flutter 不会像 UI 更改时修改旧实例 `b`,而是构建新的 Widget 实例。 框架在后台使用 RenderObjects 管理传统 UI 对象(例如维护布局状态)的许多职责。 RenderObjects 在帧之间持久存在,Flutter 的轻量级 Widgets 会告诉框架在状态之间修改 RenderObjects。 Flutter 框架处理其余部分。