创建可重用小部件的函数和类之间有什么区别? [英] What is the difference between functions and classes to create reusable widgets?

查看:19
本文介绍了创建可重用小部件的函数和类之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我意识到可以使用普通函数创建小部件而不是子类化无状态小部件.一个例子是这样的:

I have realized that it is possible to create widgets using plain functions instead of subclassing StatelessWidget. An example would be this:

Widget function({ String title, VoidCallback callback }) {
  return GestureDetector(
    onTap: callback,
    child: // some widget
  );
}

这很有趣,因为与完整的类相比,它需要的代码.示例:

This is interesting because it requires far less code than a full-blown class. Example:

class SomeWidget extends StatelessWidget {
  final VoidCallback callback;
  final String title;

  const SomeWidget({Key key, this.callback, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
      return GestureDetector(
        onTap: callback,
        child: // some widget
      );
  }
}

所以我一直在想:除了创建小部件的函数和类之间的语法之外,还有什么区别吗?使用函数是一个好习惯吗?

So I've been wondering: Is there any difference besides syntax between functions and classes to create widgets? And is it a good practice to use functions?

推荐答案

TL;DR:更喜欢使用类而不是函数来使 可重用 小部件树.

TL;DR: Prefer using classes over functions to make reusable widget-tree.

EDIT:为了弥补一些误解:这不是关于引起问题的函数,而是解决一些问题的类.

EDIT: To make up for some misunderstanding: This is not about functions causing problems, but classes solving some.

Flutter 不会有 StatelessWidget 如果一个函数可以做到同样的事情.

Flutter wouldn't have StatelessWidget if a function could do the same thing.

同样,它主要针对公共小部件,使其可重用.只使用一次的私有函数并不重要——尽管意识到这种行为仍然是好的.

Similarly, it is mainly directed at public widgets, made to be reused. It doesn't matter as much for private functions made to be used only once – although being aware of this behavior is still good.

使用函数而不是类有一个重要的区别,即:框架不知道函数,但可以看到类.

There is an important difference between using functions instead of classes, that is: The framework is unaware of functions, but can see classes.

考虑下面的小部件"功能:

Consider the following "widget" function:

Widget functionWidget({ Widget child}) {
  return Container(child: child);
}

这样使用:

functionWidget(
  child: functionWidget(),
);

它是等价的:

class ClassWidget extends StatelessWidget {
  final Widget child;

  const ClassWidget({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: child,
    );
  }
}

这样使用:

new ClassWidget(
  child: new ClassWidget(),
);


在纸面上,两者似乎做的完全一样:创建 2 个 Container,一个嵌套在另一个中.但实际情况略有不同.


On paper, both seem to do exactly the same thing: Create 2 Container, with one nested into the other. But the reality is slightly different.

在函数的情况下,生成的小部件树看起来像这样:

In the case of functions, the generated widget tree looks like this:

Container
  Container

虽然有类,小部件树是:

While with classes, the widget tree is:

ClassWidget
  Container
    ClassWidget
      Container

这很重要,因为它会改变框架在更新小部件时的行为方式.

This is important because it changes how the framework behaves when updating a widget.

通过使用函数将您的小部件树拆分为多个小部件,您会将自己暴露在错误中并错过一些性能优化.

By using functions to split your widget tree into multiple widgets, you expose yourself to bugs and miss on some performance optimizations.

不能保证您在使用函数时出现错误,但是通过使用类,您保证不会遇到这些问题.

There is no guarantee that you will have bugs by using functions, but by using classes, you are guaranteed to not face these issues.

以下是一些有关 Dartpad 的交互式示例,您可以自行运行以更好地理解问题:

Here are a few interactive examples on Dartpad that you can run yourself to better understand the issues:

https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf/>f3f1这个例子展示了类如何允许更精细地重建小部件树,提高性能

https://dartpad.dev/a869b21a2ebd2466b876a5997c9cf3f1
This example showcases how classes allow more granular rebuilds of the widget tree, improving performances

https://dartpad.dev/06842ae9e4b82fad917acb88da108eee
这个例子展示了如何通过使用函数来暴露自己在使用 InheritedWidgets(例如 Theme 或 providers)时滥用 BuildContext 并面临错误

https://dartpad.dev/06842ae9e4b82fad917acb88da108eee
This example showcases how, by using functions, you expose yourself to misusing BuildContext and facing bugs when using InheritedWidgets (such as Theme or providers)

以下是使用函数和类之间差异的精选列表:

Here's a curated list of the differences between using functions and classes:

  1. 课程:

  • 允许性能优化(const 构造函数,更精细的重建)
  • 确保在两种不同布局之间的切换正确处理资源(函数可能会重用某些先前的状态)
  • 确保热重载正常工作(使用函数可能会破坏 showDialogs 和类似的热重载)
  • 已集成到小部件检查器中.
    • 我们在 devtool 显示的小部件树中看到 ClassWidget,它有助于理解屏幕上的内容
    • 我们可以覆盖 debugFillProperties 来打印传递给小部件是
      • allow performance optimization (const constructor, more granular rebuild)
      • ensure that switching between two different layouts correctly disposes of the resources (functions may reuse some previous state)
      • ensures that hot-reload works properly (using functions could break hot-reload for showDialogs & similar)
      • are integrated into the widget inspector.
        • We see ClassWidget in the widget-tree showed by the devtool, which helps understanding what is on screen
        • We can override debugFillProperties to print what the parameters passed to a widget are
          1. 功能:

          • 代码更少(可以使用代码生成解决functional_widget)
          • 总的来说,由于这些原因,在类上使用函数来重用小部件被认为是一种不好的做法.
            可以,但将来它可能会咬你.

            Overall, it is considered a bad practice to use functions over classes for reusing widgets because of these reasons.
            You can, but it may bite you in the future.

            这篇关于创建可重用小部件的函数和类之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆