我尝试创建一个简单的表单来验证用户输入数据。
class UserForm extends StatelessWidget {
final _formKey = GlobalKey<FormState>();
final TextEditingController usernameController = TextEditingController();
UserForm({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
TextFormField(
controller: usernameController,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter something';
}
return null;
},
autovalidateMode: AutovalidateMode.onUserInteraction,
),
ElevatedButton(
onPressed: () {
print(usernameController.text);
},
child: const Text('Check'),
),
),
);
}
}当我键入某些内容并在后面删除它时,我会收到错误消息“请在textfield下输入某项内容”。
我在这里看到了一个带有表单验证的正式演示示例:https://flutter.dev/docs/cookbook/forms/validation。
现在,我的问题是:如果错误消息显示在StatefulWidget中,为什么表单需要一个StatelessWidget。TextFormField的值正在变化,而不是我创建的自定义表单小部件。
有人能解释一下什么时候使用无状态和什么时候有状态吗?
发布于 2021-10-21 12:08:47
实际上,您可以使用无状态或有状态小部件来托管表单小部件。国家将保留在这些领域本身。
但有个陷阱。如果您需要访问这些字段的内容或控制它们,则需要使用TextEditingController。当然,您可以在无状态小部件中实例化TextEditingController,但是当小部件树更新时,文本控制器将被重新实例化,因此所有数据都会丢失(光标位置和文本值)。
因此,为了保持控制器状态,您必须在有状态小部件中创建它,或者使用某种状态管理或依赖注入来将其存储在下一次更新的某个地方。
此外,TextEditingController可能会导致应用程序中的内存泄漏,所以最好在使用它之后销毁它们。您可以通过重写dispose类的State方法来做到这一点。
class MyWidgetState extends State<MyWidget> {
final controller = TextEditingController();
@override
void dispose() {
super.dispose();
controller.dispose();
}
@override
Widget build(BuildContext context) {
// ...
}
}结论
当您需要持久化值/变量时,请使用State类。小部件类将在每次构建后重新创建,因此它中的所有值都将丢失(如果不以正确的方式清理,则会导致内存泄漏),并替换为一个新实例。更新不定期进行,因此发生这种情况的可能性很低,但是如果承载表单小部件的父小部件更改其状态,那么更新也将影响表单小部件的重建。
通常,小部件只是小部件树的脚手架。它们应该只保存不可变的数据,当您需要更改数据时,您必须使用可变的State或使用其他状态管理方法。当您使用StatefulWidget时,State类的实例将被转到“下一个框架”,在该框架中,您的小部件的新实例可以使用保存来自“上一帧”的数据的状态来呈现UI。
参考文献
如果您有兴趣了解更多信息,请查看下面的链接:
发布于 2021-10-21 13:12:38
无状态或有状态的小部件都取决于您的需求。以您的例子为例,如果您的要求只是验证输入文本,那么您的示例就是完美的。如果您想在文本小部件中显示输入的文本,那么应该移到有状态小部件。
总之,如果您想要根据用户交互更改UI,那么使用一个有状态的小部件,只需要在不处理更改的情况下显示内容,就可以使用无状态小部件,如Text、Icon等正式文件。
然后,您可能会想知道示例中的验证器是如何显示错误的,因为它位于无状态小部件中。这是因为TextFormField是一个状态小部件,并根据用户交互更改UI。
正式文档显示有状态的form,因为在大多数情况下表单需要在有状态小部件中,因为它需要根据用户输入修改UI。窗体键是使用有状态小部件的另一个主要原因。如果没有有状态的小部件,就很难使用窗体键来唯一地识别小部件树中的表单。
发布于 2021-10-21 11:59:42
它应该是有状态的,因为它不仅是关于TextFormField的,而且我们通常也有其他小部件,基于TextFormField的enable/disable包含或不包含值。
示例:
bool _btnEnabled = false;
TextFormField(
...
autovalidate: true,
validator: (String txt){
if (txt.length == 10){
setState((){
_btnEnabled = true;
});
} else {
setState((){
_btnEnabled = false;
});
}
}
...
FlatButton(
onPressed: _btnEnabled == true ? yourCallback : null,
child: ...https://stackoverflow.com/questions/69661042
复制相似问题