Flutter需要内联事件处理程序,因为BuildContext是内联的



Flutter鼓励内联事件处理程序是真的吗,因为这是获取BuildContext的唯一方法?例如

class X extends StatelessWidget {
handler() {
//cannot use this if I need the BuildContext
}
Widget build(BuildContext ctx) {
return Scaffold(
home: TextButton(
text: Text("Click me"),
onPressed: () { //must be inline, cannot reference "handler" because need "ctx"
Scaffold.of( ctx ).showSnackBar(/*...*/);
}
)
)
}
}

大多数语言都鼓励通过将事件处理代码从UI中移出来简化代码,但对于Flutter,如果需要BuildContext对象,则不存在";漂亮的";除了将处理程序放在内联中之外,还有其他方法。

我弄错了吗?

大多数语言都鼓励通过将事件处理代码从UI 中移除来简化代码

事实上,这个行业的发展方式似乎是朝着这个声明性的"部件";模型我们有SwiftUI,React,Jetpack Compose等

声明性UI的部分吸引力在于,代码的层次结构与UI中创建的小部件的层次结构相匹配。Dart的语法使其非常好,例如,您可以将build方法重写为(使用Flutter 2.5.2(:

class X extends StatelessWidget {
Widget build(BuildContext context) => Scaffold(
body: TextButton(
child: Text("Click me"),
onPressed: () => Scaffold.of(context).showSnackBar(SnackBar(
content: Text("You clicked me!"),
)), 
),  
);  
}

并且缩进提供了元素如何嵌套在最终UI中的良好视觉表示。

现在,您担心内衬过多并没有错,但处理这一问题的声明性方法似乎是将组件拆分为子组件。例如,使用X小部件,TextButton可以分解为一个专门的组件:

class X extends StatelessWidget {
Widget build(BuildContext context) => Scaffold(
body: SnackButton(),
);
}
class SnackButton extends StatelessWidget {
Widget build(BuildContext context) => TextButton(
child: Text("Click me"),
onPressed: () => Scaffold.of(context).showSnackBar(SnackBar(
content: Text("You clicked me!")
)), 
);  
}

这仍然将onPressed处理程序保持在它所作用的项附近,因此代码的读者不需要四处寻找处理程序的定义。

但Flutter当初为什么要这样设计呢?为什么他们不让所有事件处理程序(onPress、onTap(默认在上下文中传递?

我可以看到一条贯穿线,从选择声明性UI到期望所有需要BuildContext的内容都将包含在build方法中,因为这样就可以按布局进行声明,而无需查看其他地方。这绝对是一种权衡(就像所有事情一样(,但我认为,如果你对实现很明智,并寻找分离组件或组件组的地方,这就不会像你现在发现的那样令人讨厌。

应该是这样的。将ctx传递给具有访问权限的函数。

class X extends StatelessWidget {
handler(BuildContext ctx) {
Scaffold.of( ctx ).showSnackBar(/*...*/);
}
Widget build(BuildContext ctx) {
return Scaffold(
home: TextButton(
text: Text("Click me"),
onPressed: () => handler(ctx) 


)
)
}
}

编辑,就像@msbit解释一样

相关内容

最新更新