第 1 部分 · 核心概念对比(Vue ↔ Flutter)
学习目标(1 天):把 Vue 里你已经熟练的概念,逐一映射到 Flutter 上。
一张总表
| Vue 概念 | Flutter 对应 | 备注 |
|---|---|---|
| Component(组件) | Widget | Flutter 万物皆 Widget,连 Padding、Center 都是 |
template |
build() 方法返回的 Widget 树 |
用 Dart 代码"写" UI,没有模板语法 |
data / ref / reactive |
State 字段 + setState |
或 ValueNotifier / Provider / Riverpod |
computed |
getter 方法 或 Selector |
Dart 里直接写 get xxx => ... |
watch |
didUpdateWidget / addListener |
或 ever(GetX)/ ref.listen(Riverpod) |
props |
构造函数参数(final 字段) |
Widget 的入参就是构造参数 |
emit |
回调函数(VoidCallback / Function) |
父组件传一个函数下来 |
v-if |
三元表达式 / if 表达式 |
condition ? A() : B() |
v-for |
List.map(...).toList() / ListView.builder |
长列表必用 ListView.builder |
v-model |
TextEditingController + onChanged |
没有自动双向绑定 |
slot |
child / children / WidgetBuilder 参数 |
把 Widget 当参数传进去 |
<style scoped> |
每个 Widget 自带样式属性 | 没有 CSS,直接传 TextStyle / BoxDecoration |
mounted |
initState() |
只在 StatefulWidget 中可用 |
unmounted |
dispose() |
释放 controller / 取消订阅 |
provide / inject |
InheritedWidget / Provider.of |
跨层传递的官方机制 |
| Vue Router | Navigator + MaterialPageRoute / go_router |
push / pop 操作栈 |
| Pinia / Vuex | Provider / Riverpod / Bloc |
选一个即可,初学先 Provider |
1. 组件 vs Widget
Vue 一个 .vue 文件 = Flutter 一个 Dart 类(继承 StatelessWidget 或 StatefulWidget)。
StatelessWidget≈ 没有data的 Vue 函数式组件,只依赖 props。StatefulWidget≈ 有data/ref的普通 Vue 组件,可以在内部维护状态。
2. 响应式:ref vs setState
Vue 改 count.value++,视图自动更新。 Flutter 改完字段后必须主动调用 setState(() { count++; }),告诉框架「这块需要重建」。
心智模型:Flutter 的
setState等同于 Vue 自动帮你做的那一步「触发更新」。
3. Props 与 Emit
ini
Vue:父 <Child :title="t" @click="onClick" />
Flutter:父 Child(title: t, onClick: onClick)
Flutter 没有"事件"概念,所有"事件"都是普通的回调函数,从父亲传给孩子。
4. 条件与列表渲染
vue
<div v-if="ok">A</div>
<div v-else>B</div>
<li v-for="item in list" :key="item.id">{{ item.name }}</li>
dart
ok ? const Text('A') : const Text('B'),
// 短列表
...list.map((item) => Text(item.name)),
// 长列表(推荐)
ListView.builder(
itemCount: list.length,
itemBuilder: (ctx, i) => Text(list[i].name),
);
5. 样式:CSS vs Widget 属性
Flutter 没有 CSS。每个 Widget 自带样式属性:
| 想做的事 | Vue/CSS | Flutter |
|---|---|---|
| 内边距 | padding: 16px |
Padding(padding: EdgeInsets.all(16), child: ...) |
| 居中 | display:flex;justify-content:center |
Center(child: ...) |
| 横向排列 | display:flex |
Row(children: [...]) |
| 纵向排列 | flex-direction:column |
Column(children: [...]) |
| 字体颜色大小 | color/font-size |
Text('x', style: TextStyle(color: ..., fontSize: ...)) |
| 圆角阴影背景 | border-radius/box-shadow/background |
Container(decoration: BoxDecoration(...)) |
6. 生命周期对照
| Vue 3 | Flutter(StatefulWidget) |
|---|---|
setup() / created |
构造函数 |
onMounted |
initState() |
onUpdated |
didUpdateWidget() |
onUnmounted |
dispose() |
7. 路由
js
// Vue
router.push({ name: 'detail', params: { id: 1 } })
dart
// Flutter
Navigator.push(context, MaterialPageRoute(
builder: (_) => DetailPage(id: 1),
));