宣告式 UI 簡介
解釋宣告式程式設計風格與指令式程式設計風格的區別。
本簡介旨在闡述 Flutter 所使用的宣告式風格與許多其他 UI 框架所使用的命令式風格之間的概念差異。
為什麼要使用宣告式 UI?
#從 Win32 到 Web,再到 Android 和 iOS,各種框架通常都使用命令式 UI 程式設計風格。這可能是你最熟悉的風格——你需要手動構建一個功能完備的 UI 實體(例如 UIView 或等效元件),並在 UI 發生變化時使用方法和設定器(setters)對其進行修改。
相比之下,為了減輕開發者編寫 UI 狀態轉換邏輯的負擔,Flutter 讓開發者只需描述當前的 UI 狀態,而將狀態轉換的任務交給框架處理。
然而,這要求我們在處理 UI 的思維方式上做出一點轉變。
如何在宣告式框架中更改 UI
#考慮以下簡化示例
在命令式風格中,你通常會找到 ViewB 的所有者,透過選擇器或 findViewById 等方法獲取例項 b,並呼叫其修改方法(並隱式地使其失效)。例如:
// Imperative style
b.setColor(red)
b.clearChildren()
ViewC c3 = new ViewC(...)
b.add(c3)
你可能還需要在 ViewB 的建構函式中重複此配置,因為 UI 的事實來源(source of truth)可能會比例項 b 本身存活得更久。
在宣告式風格中,檢視配置(如 Flutter 的 Widget)是不可變的,僅僅是輕量級的“藍圖”。若要更改 UI,Widget 會觸發自身的重建(在 Flutter 中最常見的是透過在 StatefulWidget 中呼叫 setState),並構建一個新的 Widget 子樹。
// Declarative style
return ViewB(color: red, child: const ViewC());
在這裡,Flutter 不會在 UI 發生變化時修改舊的例項 b,而是構建新的 Widget 例項。框架會在後臺處理傳統 UI 物件的大部分職責(例如維護佈局狀態),其實現方式是使用RenderObjectsRenderObjectFlutter 框架中負責佈局、繪製和命中測試的持久化物件。瞭解更多。RenderObject 是一個持久的、可變的物件,負責處理佈局、繪製和命中測試等繁重的工作。RenderObject 在幀之間保持持久,而 Flutter 的輕量級、不可變的 Widget 則作為藍圖,指示框架在狀態切換時修改 RenderObject。剩下的工作全部由 Flutter 框架處理。