flutter 父子组件互相调用方法,值更新
子组件不能直接访问父组件的属性 / 方法,核心实现方式是父组件将函数(回调)传递给子组件,子组件调用该函数(本质是 “子触发父的逻辑”)。父传子是最基础的传值方式,核心是子组件定义接收参数的变量,父组件在创建子组件时传入数据。
·
父组件向子组件传值
父传子是最基础的传值方式,核心是子组件定义接收参数的变量,父组件在创建子组件时传入数据。
实现步骤
- 子组件:通过构造函数定义需要接收的参数(推荐用 final 保证不可变);
- 父组件:创建子组件时,通过构造函数传递数据
import 'package:flutter/material.dart';
// 子组件(接收父组件传递的值)
class ChildWidget extends StatelessWidget {
// 1. 定义接收的参数(final + 构造函数必填)
final String title;
final int count;
final Color bgColor;
// 2. 构造函数(推荐用 required 标记必填参数)
const ChildWidget({
super.key,
required this.title,
required this.count,
this.bgColor = Colors.blue, // 可选参数,设置默认值
});
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});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("父传子示例")),
body: Center(
// 3. 创建子组件时传递参数
child: ChildWidget(
title: "我是父组件给的标题",
count: 99,
bgColor: Colors.lightBlue, // 覆盖默认值
),
),
);
}
}
子组件调用父组件(传值 / 调方法)
子组件不能直接访问父组件的属性 / 方法,核心实现方式是父组件将函数(回调)传递给子组件,子组件调用该函数(本质是 “子触发父的逻辑”)。
import 'package:flutter/material.dart';
// 子组件(调用父组件的回调函数传值)
class ChildWidget extends StatelessWidget {
// 1. 接收父组件传递的回调函数
final Function(String) onValueChanged;
final Function() onButtonClick;
const ChildWidget({
super.key,
required this.onValueChanged,
required this.onButtonClick,
});
Widget build(BuildContext context) {
return Column(
children: [
// 点击按钮:调用父组件的回调,传递子组件的数值
ElevatedButton(
onPressed: () {
// 2. 子组件主动调用父组件的函数,传递数据
onValueChanged("我是子组件传递给父的值");
},
child: const Text("子组件传值给父"),
),
ElevatedButton(
onPressed: () {
// 3. 子组件调用父组件的无参方法
onButtonClick();
},
child: const Text("子组件调用父组件方法"),
),
],
);
}
}
// 父组件(定义回调函数,接收子组件的值/响应调用)
class ParentWidget extends StatefulWidget {
const ParentWidget({super.key});
State<ParentWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
String _childData = "暂无数据";
// 4. 父组件定义回调函数(处理子组件传递的值)
void _handleChildValue(String value) {
setState(() {
_childData = value; // 更新父组件的状态
});
print("父组件收到子组件的值:$value");
}
// 5. 父组件定义被调用的方法
void _parentMethod() {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("父组件的方法被子组件调用了!")),
);
}
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),
// 6. 将父组件的函数传递给子组件
ChildWidget(
onValueChanged: _handleChildValue,
onButtonClick: _parentMethod,
),
],
),
),
);
}
}
子组件是 StatefulWidget,父组件调用子组件方法
如果需要父组件主动调用子组件的方法(比如子组件有一个 “重置” 方法,父组件按钮触发),需要用 GlobalKey 或 Callback 实现,这里讲最常用的 GlobalKey 方式:
import 'package:flutter/material.dart';
// 子组件(提供可被父组件调用的方法)
class ChildWidget extends StatefulWidget {
// 1. 定义 GlobalKey,关联子组件的 State
static final GlobalKey<_ChildWidgetState> childKey = GlobalKey<_ChildWidgetState>();
const ChildWidget({super.key = childKey}); // 绑定Key
State<ChildWidget> createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
int _childCount = 0;
// 2. 子组件的公开方法(供父组件调用)
void resetCount() {
setState(() {
_childCount = 0;
});
print("子组件的count被父组件重置了");
}
// 子组件的自增方法
void incrementCount() {
setState(() {
_childCount++;
});
}
Widget build(BuildContext context) {
return Column(
children: [
Text("子组件的count:$_childCount"),
ElevatedButton(
onPressed: incrementCount,
child: const Text("子组件自增"),
),
],
);
}
}
// 父组件(调用子组件的方法)
class ParentWidget extends StatelessWidget {
const ParentWidget({super.key});
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("父调用子示例")),
body: Center(
child: ColumnChildWidget
mainAxisAlignment: MainAxisAlignment.center,
children: [
const ChildWidget(), // 3. 创建子组件(已绑定Key)
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// 4. 父组件通过 GlobalKey 调用子组件的方法
ChildWidget.childKey.currentState?.resetCount();
},
child: const Text("父组件调用子组件的重置方法"),
),
],
),
),
);
}
}
void main() => runApp(const MaterialApp(home: ParentWidget()));
通过回调主动监听(有状态子组件) 子组件监听父组件值更新
import 'package:flutter/material.dart';
// 子组件:有状态,主动监听父组件参数变化
class ChildWidget extends StatefulWidget {
final int parentCount;
const ChildWidget({
super.key,
required this.parentCount,
});
State<ChildWidget> createState() => _ChildWidgetState();
}
class _ChildWidgetState extends State<ChildWidget> {
int _localCount = 0; // 子组件本地状态
// 核心生命周期:当父组件传递的参数变化时触发
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}")),
);
}
}
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16),
color: Colors.lightGreen,
child: Column(
children: [
Text("父组件count:${widget.parentCount}"),
Text("子组件本地计算值:$_localCount"),
],
),
);
}
}
// 父组件:和基础示例一致,维护动态count
class ParentWidget extends StatefulWidget {
const ParentWidget({super.key});
State<ParentWidget> createState() => _ParentWidgetState();
}
class _ParentWidgetState extends State<ParentWidget> {
int _count = 0;
void _incrementCount() {
setState(() {
_count++;
});
}
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,如果需要修改,通过回调通知父组件更新状态,再重新传值给子组件(单向数据流)。
更多推荐




所有评论(0)