首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无国籍还是无国籍?

无国籍还是无国籍?
EN

Stack Overflow用户
提问于 2021-10-21 11:19:50
回答 3查看 407关注 0票数 0

我尝试创建一个简单的表单来验证用户输入数据。

代码语言:javascript
复制
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的值正在变化,而不是我创建的自定义表单小部件。

有人能解释一下什么时候使用无状态和什么时候有状态吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-10-21 12:08:47

实际上,您可以使用无状态或有状态小部件来托管表单小部件。国家将保留在这些领域本身。

但有个陷阱。如果您需要访问这些字段的内容或控制它们,则需要使用TextEditingController。当然,您可以在无状态小部件中实例化TextEditingController,但是当小部件树更新时,文本控制器将被重新实例化,因此所有数据都会丢失(光标位置和文本值)。

因此,为了保持控制器状态,您必须在有状态小部件中创建它,或者使用某种状态管理或依赖注入来将其存储在下一次更新的某个地方。

此外,TextEditingController可能会导致应用程序中的内存泄漏,所以最好在使用它之后销毁它们。您可以通过重写dispose类的State方法来做到这一点。

代码语言:javascript
复制
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。

参考文献

如果您有兴趣了解更多信息,请查看下面的链接:

票数 2
EN

Stack Overflow用户

发布于 2021-10-21 13:12:38

无状态或有状态的小部件都取决于您的需求。以您的例子为例,如果您的要求只是验证输入文本,那么您的示例就是完美的。如果您想在文本小部件中显示输入的文本,那么应该移到有状态小部件。

总之,如果您想要根据用户交互更改UI,那么使用一个有状态的小部件,只需要在不处理更改的情况下显示内容,就可以使用无状态小部件,如Text、Icon等正式文件

然后,您可能会想知道示例中的验证器是如何显示错误的,因为它位于无状态小部件中。这是因为TextFormField是一个状态小部件,并根据用户交互更改UI。

正式文档显示有状态的form,因为在大多数情况下表单需要在有状态小部件中,因为它需要根据用户输入修改UI。窗体键是使用有状态小部件的另一个主要原因。如果没有有状态的小部件,就很难使用窗体键来唯一地识别小部件树中的表单。

票数 0
EN

Stack Overflow用户

发布于 2021-10-21 11:59:42

它应该是有状态的,因为它不仅是关于TextFormField的,而且我们通常也有其他小部件,基于TextFormFieldenable/disable包含或不包含值。

示例:

代码语言:javascript
复制
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: ...
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69661042

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档