Skip to content

Compose / Flutter / Vue 状态管理对照

三端状态管理的核心不是“选哪个库”,而是 状态如何单向流动、如何分层、如何避免 UI 与业务状态打架

一句话定义

  • Compose:强调状态到 UI 的直接映射,天然贴合单向数据流
  • Flutter:方案多,重点在于别只停留在 setState
  • Vue:响应式系统天然强,但也要分清局部状态与全局状态

为什么需要

很多“状态管理混乱”并不是库的问题,而是边界没分好:

  • UI state 和业务 state 混在一起
  • 一次性事件和持久状态混在一起
  • 页面级状态、缓存状态、全局共享状态全堆进一个容器

所以这篇文档的重点不是“哪个框架更强”,而是对照它们解决的本质问题。

底层机制

1. Compose:状态驱动 UI 是默认姿势

Compose 天然鼓励:

  • 状态在外部
  • UI 根据状态重组
  • 事件向上抛
  • 单向流动

这使它和 StateFlow / ViewModel 很容易组合。

2. Flutter:灵活,但容易从灵活变混乱

Flutter 可以:

  • setState
  • ValueNotifier
  • Provider
  • Riverpod
  • Bloc
  • GetX

问题不在工具多,而在于:

  • 小页面容易乱用全局状态
  • 大页面如果一直只靠 setState 会难维护

3. Vue:响应式天然顺手,但仍要做分层

Vue 的优势是:

  • ref/reactive 很轻巧
  • 组件通信自然
  • Pinia 适合集中管理

但如果所有状态都放全局 store,仍会和 Flutter / Android 遇到同样的问题:边界不清、依赖扩散。

Android / Flutter / Web / Backend 对照

维度ComposeFlutterVueBackend
默认 UI 响应模型状态驱动重组Widget rebuild响应式依赖追踪无 UI
推荐主线ViewModel + StateFlowRiverpod / 分层状态Pinia + 局部响应式DTO / domain state
常见误区事件和状态混放setState 扛全场全局 store 过载把前端状态逻辑后推过多

常见场景

1. 列表页 + 详情页 + 筛选条件

这类页面通常至少有三层状态:

  • 页面 UI 状态(loading、展开、选中)
  • 业务状态(列表数据、筛选条件)
  • 缓存/持久状态(本地已保存配置)

如果三层不分,换哪个库都乱。

2. 一次性事件

比如:

  • Snackbar
  • Toast
  • 导航跳转
  • 支付成功弹窗

这类不是持久状态,不应和页面状态放同一字段长期保存。

3. 配置变更 / 页面恢复

Compose、Flutter、Vue 虽然宿主不同,但共同问题是:

  • 哪些状态该丢
  • 哪些状态该保
  • 哪些状态要恢复

常见坑

现象修法
所有状态全放一个对象修改牵一发而动全身分页面态/业务态/缓存态
一次性事件当持久状态重进页面重复消费事件流单独建模
小页面直接上很重架构维护成本高简单场景先轻量处理
大页面长期只靠局部 setState/局部响应式状态散落及时抽到统一状态层

与相近概念对比

概念更适合解决什么
Compose + StateFlowAndroid 单向数据流 UI
RiverpodFlutter 中大型项目分层状态
setState小范围局部状态
Vue ref/reactive组件内局部响应式
PiniaVue 全局共享状态

对应实验

目前本主题先以主线文档为主;后续建议你在真实项目问题中反推哪些状态模型最值得做 lab。

复习检查题

  1. 为什么说状态管理问题常常不是“选库问题”,而是“边界问题”?

    :因为页面态、业务态、缓存态、一次性事件如果混在一起,无论用什么库都会变乱;库只是承载手段,边界划分才是根问题。

  2. 为什么一次性事件不能简单当持久状态?

    :因为它的语义是“消费一次即结束”,如果当持久状态保存,页面重建或重进时容易重复触发。

  3. Compose / Flutter / Vue 状态管理最共同的原则是什么?

    :让状态有清晰来源、单向流动、分层明确,并避免 UI 细节与业务状态互相污染。

速记

  • 真问题:状态边界,不是库名字
  • 页面态 / 业务态 / 缓存态要分层
  • 事件不要伪装成状态
  • 小场景轻,大场景及时抽象