父组件向子组件传值
父传子是最基础的传值方式,核心是子组件定义接收参数的变量,父组件在创建子组件时传入数据。
实现步骤
- 子组件:通过构造函数定义需要接收的参数(推荐用 final 保证不可变);
- 父组件:创建子组件时,通过构造函数传递数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| import 'package:flutter/material.dart';
class ChildWidget extends StatelessWidget { final String title; final int count; final Color bgColor;
const ChildWidget({ super.key, required this.title, required this.count, this.bgColor = Colors.blue, });
@override Widget build(BuildContext context) { return Container( color: bgColor, padding: const EdgeInsets.all(16), child: Column( children: [ Text("父组件传递的标题:$title"), Text("父组件传递的数字:$count"), ], ), ); } }
class ParentWidget extends StatelessWidget { const ParentWidget({super.key});
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("父传子示例")), body: Center( child: ChildWidget( title: "我是父组件给的标题", count: 99, bgColor: Colors.lightBlue, ), ), ); } }
|
子组件调用父组件(传值 / 调方法)
子组件不能直接访问父组件的属性 / 方法,核心实现方式是父组件将函数(回调)传递给子组件,子组件调用该函数(本质是 “子触发父的逻辑”)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| import 'package:flutter/material.dart';
class ChildWidget extends StatelessWidget { final Function(String) onValueChanged; final Function() onButtonClick;
const ChildWidget({ super.key, required this.onValueChanged, required this.onButtonClick, });
@override Widget build(BuildContext context) { return Column( children: [ ElevatedButton( onPressed: () { onValueChanged("我是子组件传递给父的值"); }, child: const Text("子组件传值给父"), ), ElevatedButton( onPressed: () { onButtonClick(); }, child: const Text("子组件调用父组件方法"), ), ], ); } }
class ParentWidget extends StatefulWidget { const ParentWidget({super.key});
@override State<ParentWidget> createState() => _ParentWidgetState(); }
class _ParentWidgetState extends State<ParentWidget> { String _childData = "暂无数据";
void _handleChildValue(String value) { setState(() { _childData = value; }); print("父组件收到子组件的值:$value"); }
void _parentMethod() { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("父组件的方法被子组件调用了!")), ); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("子调用父示例")), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("子组件传递的值:$_childData"), const SizedBox(height: 20), ChildWidget( onValueChanged: _handleChildValue, onButtonClick: _parentMethod, ), ], ), ), ); } }
|
如果需要父组件主动调用子组件的方法(比如子组件有一个 “重置” 方法,父组件按钮触发),需要用 GlobalKey 或 Callback 实现,这里讲最常用的 GlobalKey 方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| import 'package:flutter/material.dart';
class ChildWidget extends StatefulWidget { static final GlobalKey<_ChildWidgetState> childKey = GlobalKey<_ChildWidgetState>();
const ChildWidget({super.key = childKey});
@override State<ChildWidget> createState() => _ChildWidgetState(); }
class _ChildWidgetState extends State<ChildWidget> { int _childCount = 0;
void resetCount() { setState(() { _childCount = 0; }); print("子组件的count被父组件重置了"); }
void incrementCount() { setState(() { _childCount++; }); }
@override Widget build(BuildContext context) { return Column( children: [ Text("子组件的count:$_childCount"), ElevatedButton( onPressed: incrementCount, child: const Text("子组件自增"), ), ], ); } }
class ParentWidget extends StatelessWidget { const ParentWidget({super.key});
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("父调用子示例")), body: Center( child: ColumnChildWidget mainAxisAlignment: MainAxisAlignment.center, children: [ const ChildWidget(), const SizedBox(height: 20), ElevatedButton( onPressed: () { ChildWidget.childKey.currentState?.resetCount(); }, child: const Text("父组件调用子组件的重置方法"), ), ], ), ), ); } }
void main() => runApp(const MaterialApp(home: ParentWidget()));
|
通过回调主动监听(有状态子组件) 子组件监听父组件值更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| import 'package:flutter/material.dart';
class ChildWidget extends StatefulWidget { final int parentCount;
const ChildWidget({ super.key, required this.parentCount, });
@override State<ChildWidget> createState() => _ChildWidgetState(); }
class _ChildWidgetState extends State<ChildWidget> { int _localCount = 0;
@override void didUpdateWidget(covariant ChildWidget oldWidget) { super.didUpdateWidget(oldWidget); if (widget.parentCount != oldWidget.parentCount) { print("子组件监听到父组件count变化:${oldWidget.parentCount} → ${widget.parentCount}"); setState(() { _localCount = widget.parentCount * 2; }); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("父组件count更新为:${widget.parentCount}")), ); } }
@override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(16), color: Colors.lightGreen, child: Column( children: [ Text("父组件count:${widget.parentCount}"), Text("子组件本地计算值:$_localCount"), ], ), ); } }
class ParentWidget extends StatefulWidget { const ParentWidget({super.key});
@override State<ParentWidget> createState() => _ParentWidgetState(); }
class _ParentWidgetState extends State<ParentWidget> { int _count = 0;
void _incrementCount() { setState(() { _count++; }); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("主动监听父组件值更新")), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ChildWidget(parentCount: _count), const SizedBox(height: 20), ElevatedButton( onPressed: _incrementCount, child: const Text("增加父组件count"), ), ], ), ), ); } }
void main() => runApp(const MaterialApp(home: ParentWidget()));
|
核心逻辑
- didUpdateWidget 是 StatefulWidget 的生命周期方法,仅在父组件传递的参数变化时触发;
- 通过对比 oldWidget(旧参数)和 widget(新参数),可以精准判断哪些值发生了变化;
- 在方法内可以执行任意自定义逻辑(更新本地状态、弹提示、调用方法等),实现 “主动监听”。
注意事项
- 子调用父的核心逻辑:父组件传递 “函数” 给子组件,子组件执行该函数(可传参),本质是 “回调”,而非子组件直接访问父组件;
- GlobalKey 注意点:
- 仅用于父调用子的场景,不要滥用(可能影响性能);
- currentState 可能为 null,需加 ? 空安全判断;
- 状态管理:如果组件层级较深(超过父子),不建议用回调 / GlobalKey,推荐用 Provider/GetX/Riverpod 等状态管理库;
- 不可变原则:父传子的参数推荐用 final,如果需要修改,通过回调通知父组件更新状态,再重新传值给子组件(单向数据流)。