

子玥酱 (掘金 / 知乎 / CSDN / 简书 同名)
大家好,我是 子玥酱,一名长期深耕在一线的前端程序媛 👩💻。曾就职于多家知名互联网大厂,目前在某国企负责前端软件研发相关工作,主要聚焦于业务型系统的工程化建设与长期维护。
我持续输出和沉淀前端领域的实战经验,日常关注并分享的技术方向包括 前端工程化、小程序、React / RN、Flutter、跨端方案,
在复杂业务落地、组件抽象、性能优化以及多端协作方面积累了大量真实项目经验。
技术方向: 前端 / 跨端 / 小程序 / 移动端工程化 内容平台: 掘金、知乎、CSDN、简书 创作特点: 实战导向、源码拆解、少空谈多落地 **文章状态:**长期稳定更新,大量原创输出
我的内容主要围绕 前端技术实战、真实业务踩坑总结、框架与方案选型思考、行业趋势解读 展开。文章不会停留在"API 怎么用",而是更关注为什么这么设计、在什么场景下容易踩坑、真实项目中如何取舍,希望能帮你在实际工作中少走弯路。
子玥酱 · 前端成长记录官 ✨
👋 如果你正在做前端,或准备长期走前端这条路
📚 关注我,第一时间获取前端行业趋势与实践总结
🎁 可领取 11 类前端进阶学习资源 (工程化 / 框架 / 跨端 / 面试 / 架构)
💡 一起把技术学"明白",也用"到位"
持续写作,持续进阶。
愿我们都能在代码和生活里,走得更稳一点 🌱
文章目录
-
- 引言
- 什么是"止损"?不是不出问题,而是问题可控
- [Flutter / RN / iOS 的状态复杂度,从哪里开始分化?](#Flutter / RN / iOS 的状态复杂度,从哪里开始分化?)
-
- [Flutter 和 RN:状态天生"外溢"](#Flutter 和 RN:状态天生“外溢”)
- iOS:强约束换来的"慢复杂"
- [Flutter / RN 为什么更容易"自然膨胀"?](#Flutter / RN 为什么更容易“自然膨胀”?)
-
- 原因一:状态提升太容易了
- 原因二:全局状态是"无形扩散"的
- [原因三:组件边界 ≠ 状态边界](#原因三:组件边界 ≠ 状态边界)
- [为什么 iOS 更容易"止损"?](#为什么 iOS 更容易“止损”?)
-
- [ViewController 天然是一个"止损点"](#ViewController 天然是一个“止损点”)
- [iOS 的"反应慢",反而是优点](#iOS 的“反应慢”,反而是优点)
- [Flutter / RN 真就没救了吗?](#Flutter / RN 真就没救了吗?)
- [Flutter / RN 项目如何提前"止损"?](#Flutter / RN 项目如何提前“止损”?)
- 总结
引言
如果你做过两年以上的 App 维护,大概率会有一个共识:
真正拖垮项目的,几乎都不是性能,而是状态。
不是首屏慢一点,不是列表掉几帧,而是某一天你发现:
- 一个需求改动,需要改 10 个文件
- 一个状态变更,不知道会影响多少页面
- 一个 bug 修完,三天后在别的地方又冒出来
这篇文章不聊「谁性能更好」,而是换一个更现实的问题:
Flutter / RN / iOS,在长期维护下,谁更容易及时止损?
什么是"止损"?不是不出问题,而是问题可控
先说清楚这里的「止损」是什么意思。
不是系统永远不复杂,而是当复杂度开始失控时,你是否有能力:
- 快速定位状态来源
- 限定影响范围
- 局部重构而不是推倒重来
从这个角度看,止损能力本质上是架构对复杂度的容忍度。
Flutter / RN / iOS 的状态复杂度,从哪里开始分化?
Flutter 和 RN:状态天生"外溢"
Flutter 和 RN 有一个共同点:
UI 是状态的函数。
text
UI = f(state)
这带来两个直接结果:
- 状态一多,UI 复杂度指数级增长
- 状态一旦共享,影响面天然扩大
Flutter 的 build,RN 的 render,本质上都在做同一件事:
状态变化 → 重新描述 UI
问题不在于这个模式错,而在于:
它对状态结构的要求极高,但工具并不会强制你做好结构。
iOS:强约束换来的"慢复杂"
对比之下,iOS(UIKit / MVC / MVVM)反而显得「笨重」。
- ViewController 是边界
- 状态大多私有
- 跨页面状态需要明确传递
这意味着什么?
- 状态传播成本高
- 架构扩展速度慢
- 但复杂度增长是线性的
你很难不小心把整个 App 的状态绑在一起。
Flutter / RN 为什么更容易"自然膨胀"?
原因一:状态提升太容易了
在 Flutter / RN 中,你可能经常做这样的事情:
- 子组件需要状态
- 兄弟组件要共享
- 状态被提到父组件
- 父组件又不够用
- 最后进全局 Store / Provider / Bloc
看起来每一步都合理,但最终结果是:
状态逐渐失去"归属感"。
原因二:全局状态是"无形扩散"的
来看一个 Flutter 中非常常见的写法:
dart
final counterProvider = StateProvider<int>((ref) => 0);
然后:
dart
ref.watch(counterProvider);
乍一看没问题,但长期下来你会发现:
- 谁在用这个状态?
- 用来干什么?
- 改动会影响哪些页面?
Provider 本身不会告诉你答案。
原因三:组件边界 ≠ 状态边界
在 Flutter / RN 中,组件拆分做得再细:
- Widget / Component 很清晰
- 但状态可能还是集中在一起
这就造成一个错觉:
"我组件拆得很干净,架构应该没问题。"
实际上,状态可能早已纠缠成一团。
为什么 iOS 更容易"止损"?
不是因为 iOS 开发者更自律,而是因为:
系统在逼你为状态负责。
ViewController 天然是一个"止损点"
在 UIKit 中:
- 页面状态默认不共享
- 生命周期明确
- 状态销毁时机清晰
你想把状态搞成全局,反而要写很多代码。
这带来一个好处:
状态泄漏是"显性的",不是悄无声息的。
iOS 的"反应慢",反而是优点
在 iOS 中:
- 状态跨页面需要设计
- 全局状态需要明确入口
- 重构成本早期就暴露
这让很多问题提前暴露,而不是后期爆炸。
Flutter / RN 真就没救了吗?
当然不是。
问题不在技术,而在于:
Flutter / RN 把"状态刹车"这件事,交给了架构设计。
一个通用的"止损型"状态分层方法
无论 Flutter / RN / iOS,其实都可以用同一套思路:
页面私有状态
- 滚动位置
- 选中态
- loading / error
原则:页面销毁,状态必须一起销毁。
Flutter 示例:
dart
class CounterPage extends StatefulWidget {
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int count = 0;
void increment() {
setState(() {
count++;
});
}
@override
Widget build(BuildContext context) {
return Text('$count');
}
}
这种状态永远不应该进全局。
业务模块状态
- 登录态
- 用户信息
- 业务流程中间态
特点:
- 有明确业务边界
- 生命周期长于页面
- 不等于全局共享
Flutter(Riverpod 示例):
dart
final userProvider = StateNotifierProvider<UserNotifier, User?>(
(ref) => UserNotifier(),
);
class UserNotifier extends StateNotifier<User?> {
UserNotifier() : super(null);
void login(User user) {
state = user;
}
void logout() {
state = null;
}
}
关键不是用什么库,而是限制它的使用范围。
真正的全局只读状态
- 配置
- Feature 开关
- 环境信息
原则只有一个:
全局状态应该是"被依赖的",而不是"被修改的"。
Flutter / RN 项目如何提前"止损"?
结合真实项目经验,有几个非常实用的判断标准:
- 一个状态是否能明确说出「属于谁」
- 是否能画出状态影响范围
- 删除一个页面,是否需要修改状态定义
- 新同事是否能快速理解状态流向
如果这些问题开始模糊:
不是再选一个新状态库,而是该重构状态边界了。
总结
- iOS:止损能力强,但扩展慢
- Flutter / RN:扩展快,但需要主动刹车
- 真正决定生死的不是技术,而是状态设计意识
Flutter 和 RN 并不危险,危险的是:
用"写 UI 的思路"去管理"系统级状态"。
如果你能在架构层提前踩刹车,Flutter 完全可以成为一个长期可维护的技术选择。