我试图了解我作为参数传递给子小部件的函数如何能够更新父小部件的实例属性。
例如,以下代码有效:
//...some code
DesignedContainer(
colour: selectedGender == Gender.male
? activeCardColor
: inactiveCardColor,
cardChild: const GenderWidget(
genderIcon: FontAwesomeIcons.mars,
genderName: 'MALE',
),
stateReset: () { //Note this function, I will change this below
setState(() {
selectedGender = Gender.male;
});
},
),
//...some code
class DesignedContainer extends StatefulWidget {
const DesignedContainer({
this.colour = const Color(0xFF1D1E33),
this.cardChild,
this.stateReset,
super.key,
});
final Widget? cardChild;
final Color colour;
final VoidCallback? stateReset;
@override
State<DesignedContainer> createState() => _DesignedContainerState();
}
class _DesignedContainerState extends State<DesignedContainer> {
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: widget.stateReset, //I shall change this too
child: Container(
margin: const EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: widget.colour,
borderRadius: BorderRadius.circular(10.0),
),
child: widget.cardChild,
),
);
}
}
如果我更改上面的代码,以便将 setState 移动到DesignedContainer小部件,如下所示:
//Inside the parent widget:
stateReset: () => selectedGender = Gender.male,
//some code
//Inside the child widget:
onTap: (){
setState(() {
widget.stateReset!();
});
}
我希望两个版本都能工作,但后者不起作用。我不明白为什么。
在第一个版本中,
DesignedContainer
位于有状态小部件内;我们将其称为 MyWidget
以及关联的 MyWidgetState
。因此,当您指定:
stateReset: () => setState(...),
setState
指的是MyWidgetState.setState
。为什么?
“闭包是一个函数对象,它可以访问其词法作用域中的变量,即使该函数在其原始作用域之外使用。函数可以关闭周围作用域中定义的变量。”
来源:https://dart.dev/language/functions#lexical-closures
周围范围就是
build
的MyWidgetState
方法。在该作用域中,您可以访问 MyWidgetState.setState
方法,然后在传递给 stateReset
参数的函数的词法作用域中捕获该方法。
由于词法作用域可用,因此可用 即使该函数在其原始作用域之外使用,该调用也会正确地从其他小部件调用
MyWidgetState.setState
。
在第二个示例中,您将调用
setState
的 DesignedContainer.setState
。
这些不一样,第一个重建其关联的小部件,第二个重建DesignedContainer。
您可以推理为什么对第一种情况使用相同的原则。