Flutter: 将类似 JSX 视为 React Native

创建于 2018-03-25  ·  203评论  ·  资料来源: flutter/flutter

对于构建 UI 的代码必须是可读的。 我知道 Dart 有点像 Java 的简单版本,但它并不是真正用于构建 UI 的编程语言。 例如,它没有结束标签。 结果,很难用这个不可读的代码在脑海中构建一个画面。

此外,Flutter 受到了 React 的启发。 Flutter 没有 JSX 怎么会有这种不可读的代码? 我很害怕 Flutter 很快就会像 AnglurJs 的早期那样消亡。

我知道在 Google 工作的人很聪明,但我们也有一些不是很聪明的人选择 React 而不是 Dart,这也是过去 Dart 死的原因之一。

最有用的评论

有些人喜欢 jsx,有些人不喜欢。 为什么不支持两种方式实现 UI。 可以写出类似jsx的语法,终于可以用flutter原生语法了,为什么不支持呢?

所有203条评论

这个问题问了很久:
https://github.com/flutter/flutter/issues/11609
开发的功能原型:
https://spark-heroku-dsx.herokuapp.com/index.html
这显示了替代方案和一些好处......


DSX 当前的问题是与 Flutter 工具的正确集成,以便为 .dsx 文件上的调试器、自动完成等提供出色的开发人员体验。

告诉用户他们可以使用 DSX 但不能使用调试器或享受自动完成功能对我来说是行不通的。 如果有人想提供帮助,我需要想办法为 Dart 工具和 VS Code Dart 插件添加完整的预处理支持(带有源映射)。一旦工具支持 DSX 或任何其他转译语言(任何语言是 Dart 的超集,但将所有内容都编译为 Dart)就可以了。

如果您可以并且愿意提供帮助,请告诉我。

我不能同意。 尤其是使用像 Dart Code 这样的 IDE,您可以获得虚拟结束标签,这使得阅读变得更容易。 使用 Dart2 可以省略new它甚至会变得更好。

此外,我发现它不鼓励您构建太大的 Widget 树而不将其解构为更易于维护的小部件类。

我使用安卓工作室。 我什至没有看到一个虚拟的结束标签。 即使我们有一个虚拟的结束标签,它也比每个人都讨厌的 HTML 更复杂。 Dart 只是一种编程语言。 谷歌的人不明白简化的重要性。

close

我也不认为我想要类似 JSX 的语法,但是是的,我使用 IntelliJ 并且需要使用工具完成一些操作,以便 UI 代码更易于理解。

此外,我发现它不鼓励您构建太大的 Widget 树而不将其解构为更易于维护的小部件类。

我看不出这与 JSX 有什么不同……随着树变大,您可以将两者分成更小的子树。

我也不认为我想要类似 JSX 的语法,但是是的,我使用 IntelliJ 并且需要使用工具完成一些操作,以便 UI 代码更易于理解。

它应该在所有平台上都易于阅读,而不仅仅是 Intellij; 我的意思是在审查代码时应该很容易在 Bitbucket 上阅读; 并且在使用任何编辑器时也应该有效; 我的意思是使用这些“注释注释”,如果有人使用“vi”在其中键入不同的注释会发生什么?

这是锁定 #11609 的副本
@sethladd

抱歉,您应该在 IntelliJ 和 Android Studio 中看到“虚拟结束标签”。

cc @devoncarew验证哪个版本打开了它,或者用户是否需要选择加入?

我们感谢您对以下内容的评论:类似 JSX 的语法。 我们相信跨语言、我们的工具和插件有机会让编辑 UI 代码更容易。

这确实欺骗了#11609,但如果可能的话,我希望@devoncarew或@mit-mit 添加关于如何打开“虚拟结束标签”的注释。

谢谢!

@JonathanSum ,不幸的是,Android Studio 3.0 中没有结束标签。 您至少需要 IntelliJ 2017.3 或 Android Studio 3.1。 Android Studio 3.1 目前处于候选发布阶段,我们计划明天发布一个支持它的 Flutter 插件。

不管围绕类似 JSX 语法的讨论如何,我们都希望努力使在 Dart、IntelliJ / Android Studio 和 VS Code 中编写 UI 代码变得更容易。 这是最初的结束标签工作,也是最近的 Flutter Outline 视图。 这在大纲视图中显示了您的 build() 方法的结构,并允许您导航小部件并更轻松地查看它们的父/子关系。 目前在 IntelliJ 中可用 - 我们确实希望能够将它带到 VS Code 中。

@zoechi - 这可能是一个骗局; 但是另一根线变热了,被锁住了。 因此,他们无法为该对话做出贡献。 我认为你不应该仅仅因为你不喜欢人们要求一个功能就关闭这个线程。 这应该是响应新来的新人并请求 JSX 支持(或类似功能)的新线程。


@sethladd - 请不要锁定这个线程; 我确实认为让社区讨论替代布局方法的优缺点是有用的。 如果它没有被锁定,我会参加#11609。


我来自 NativeScript 背景。 我不得不说这是我觉得 NativeScript 比 Flutter 更容易使用的一个领域。 我可以在不到 5 分钟的时间内完成一个相当复杂的屏幕,并轻松快速地迭代设计。 然后添加运行屏幕的代码。

在 NativeScript 中,我们实际上有以下文件:

  • screen.js / screen.ts (如果你喜欢打字稿,.ts 会被转译成 .js)。 这是您正在显示的屏幕的主要逻辑。
  • screen.css (或screen.android.css和/或screen.ios.css )这是一个更有限的 CSS 版本,但支持高度、宽度、颜色、背景等。大多数时候只需要一个 css 文件,但有时如果你在做一些奇怪的事情,你可能会将你的 css 分开用于 android 和 ios。 它完全支持类、元素和 id,所以我可以做TextArea.Login #Password ,它实际上会将自己限制在特定的元素链中。
  • screen.xml (再次或screen.android.xml和/或screen.ios.xml ) - 这是屏幕布局。 如果需要,您可以在 JS 中对布局进行编码(基本上就像 Flutter 一样); 但是 XML 就简单多了。 例子:
<Page onLoad="loadme">
    <ActionBar title="Blah"><NavigationButton click="back" title="Back"/></ActionBar>
    <StackLayout>
      <Label text="Hi" id="Hi" style="color: red"/>
     <Label text="{{name}}" class="name"></Label>
     <Button text="Click Me" tap="clicker"/>
    </StackLayout></Page>

有趣的是,ActionBar 是一个特定的 page only 组件(即它特定于唯一的 Page); 所以基本上发生的是 XML 解析器 See 的页面; 创建一个新的页面元素; 然后创建一个 ActionBar 组件,然后在 Page 组件上运行 builderChild 函数; 页面组件覆盖默认的builderChild,并查看子组件是否为ActionBar; 如果是; 然后它在内部将其分配给适当的变量; 否则,其余部分将通过 parent/super 传递,然后自动将其分配给“child”或“children”组件。 构建系统非常通用,因为每个组件都可以使用父级的 builderchild 函数或覆盖它来执行额外的项目,如支持<Label>Hi</Label>并自动将其分配给 Text 值。 这使得布局非常容易启动和运行,无需任何代码。

因为大多数编辑器都具有良好的 XML 编辑能力,所以它会自动着色,并使用正确的 xsd 定义 intellij (& vscode) 进行自动检查和有限的上下文支持。

现在从技术上讲,一切实际上都是一个 JavaScript 组件; 所以你可以手动完成所有这些(就像 Flutter 所做的那样); 但我发现在 NativeScript 中布局屏幕很容易。 并且你第一次开始时不需要 JS 或 CSS; 然后您可以添加 CSS(通常您不会在布局中对基于 CSS 的属性进行硬编码;但如果您愿意,也可以)。

这样做的好处是; 它是否允许 Web 开发人员只需很少(如果有的话)再培训就可以直接投入使用。 实际上; 因为它灵活的渲染器和基于 JS 的——NativeScript 实际上支持 Angular 和 Vue——​​所以如果你使用 Angular 或 Vue,你实际上可以在 web 和你的移动应用程序之间共享接近 95% 的代码库。 因为它使用原生操作系统组件,比如 react native(而不是像 cordova 这样的 webview); 它确实是一个不错的跨平台系统(比 React Native 更好)。 但是,我可以看到 Flutter 有哪些优势使其成为某些移动开发的良好补充工具,因为它们是 NativeScript 更差的一些应用程序,而有些应用程序仍然更好,并且基于对我的回复伊恩的问题; 将在这些领域保持更好的工具。

最好打开那个锁定的线程并将这些评论复制到那里,这样我们就有了完整讨论的历史。

@JonathanSum这与是否有人想要或不想要该功能无关,
就是这里是不是可以热议的地方。 我猜 reddit 或类似网站是更好的地方。

@cbazza - 我不反对; 但是以后你必须非常小心,不要影射有关人的事情。 这只会激起讨论,无论你认为他们多么愚蠢。

@zoechi - 实际上我相信任何关于新功能的讨论都应该在这里。 应该保留历史,以便当 John Doe 从现在开始一个月后搜索 XYZ 功能时,他可以:+1:现有功能和/或对其做出贡献。

由于我的评论,我不认为该线程真的被锁定了这么长时间。 如果我说的很糟糕,我怎么能评论其他所有内容,例如这个线程?

线程被锁定是因为 Flutter 团队对此没有兴趣,只是希望人们停止谈论它。

让我们将本期的讨论集中在类似 JSX 的特性的用例和示例上。

实际上,如果 NativeScript 这么好,为什么要费心费力地使用 Flutter 而不是试图让 Flutter NativeScript 像这样。
我来自基于 XML 的平台(Xamarin Forms),一开始我认为在代码中设计可能会更困难,但事实并非如此。
相反,它很容易将您的设计分解为易于维护的单独类。

JSX 在代码中设计!!!

@sethladd

让我们将本期的讨论集中在类似 JSX 的特性的用例和示例上。

好的,让我们谈谈我的 DSX 设计,可以在这里查看:
https://spark-heroku-dsx.herokuapp.com/index.html

它提供了与当前构建小部件的方式的直接映射,同时提供了一种类似 JSX 的风格,这种风格非常轻量级并且对于 React 开发人员来说很熟悉。 这个设计有什么遗漏吗? 这种设计能在野外生成所有可能的小部件吗?

根据经验,如果您觉得一个感叹号还不够,您可能应该离开键盘并休息一下。

我是 Flutter 的新手,只对 Android 和 Java 有一些经验,我必须说我发现 Flutter 提供的东西比这里提出的要好得多。 我倾向于发现 XML 丑陋且笨拙。 拥有一个独特的结束角色比拥有一片汪洋大海要美丽得多这使我的代码长了 5 倍,这是我在编辑 Android XML 时的仇恨,而且只是人们使用的绝大多数 IDE 都支持的虚拟结束标签。 这在设计更长的结构时非常有用。 在我看来,整洁的嵌套 XML 并没有超过其他缺点,尤其是当 'child:/children:' 做得几乎一样好时。 Dart 非常干净,这也是我非常喜欢它的一个原因。 如果这被毁了,我会非常失望。

我知道 React 是这样做的,但上次我检查时,这个地方说 Flutter。 仅仅因为 React 这样做并不意味着我们必须这样做——你不是唯一一个跳船到这里的人! 我非常同意@escamoteur提出的所有观点。 我没有看到添加人们在使用 Flutter 时需要处理的另一种语言的意义。 我们已经在使用 Dart 进行大部分编程,我们不需要大量其他东西来掌握! 必须重视一致性和简单性。

您的 DSX 与生成的 Dart 片段的一些评论:

  1. 主观:我没有看到任何明显的可读性提升。 冗长是相似的——如果不是更长一点的话。 Dart IDE 插件提供自动关闭标签,它反映声明性标记关闭标签。 如果 JSX 是用代码设计的,那么我看不出 Dart 中的小部件不是。

  2. <vars>中的多个属性

@<vars>
var textStyle = {
    "textDirection": "TextDirection.ltr",
    "textAlign": "TextAlign.center",
    "overflow": "TextOverflow.ellipsis",
    "style": "new TextStyle(fontWeight: FontWeight.bold)"
};
</vars>@

能够定义混合多个属性的全局样式是一个好主意。
然而,当我回顾我适度的颤振体验时,我看不出我会在哪里使用这些。

对于Text ,似乎我需要重用的大部分内容是在TextStyle中定义的,而不是几个属性的混合。 也许您可以找到除Text之外的另一个示例,但情况并非如此。

查看TextStyle ,我发现当前的不可变 + copy() 非常适合在 Dart 中重用和编写:

class Style {
  static const TextStyle avenirNextMedium =
      const TextStyle(
         fontFamily: 'Avenir Next', 
         fontWeight: FontWeight.w500,
      );

  static TextStyle title =
      avenirNextMedium.copyWith(
        color: ColorKit.blue, 
        fontSize: 45.0,
      );
}

new Text(
  'Hello',
  style: Style.title,
),

new Text(
  'Hello2',
  style: Style.title.copyWith(
    color: ColorKit.red,
  ),
),

对于共享相同样式的可重用Container ,我认为创建自定义无状态小部件比外部定义的<vars>效果更好。 大多数时候,我还想要填充、墨水、手势监听器或阴影。

对于任何这些情况,我都需要将Container与另一个小部件组合在一起: MaterialPaddingCenter等。所以如果我必须创建一个无论如何,自定义可重用“容器”小部件,我认为拥有一个外部<vars>样式只会定义我的可重用小部件层次结构中单个小部件的属性并没有太大的好处。

我不认为 Flutter 的“一切都是小部件”与“多属性”样式配合得很好。

  1. 在您当前的 DSX 示例中未突出显示:您将如何使用动态小部件编写界面? 含义:如何根据条件显示或不显示某些小部件。

在 Dart 中进行设计时,在children中添加或不添加特定小部件非常方便。
用另一个小部件动态包装一个小部件也非常方便。 它使 build() 函数流畅且易于理解。

    var children = <Widget>[];
    if(a) {
      children.add(wa);
    }

    var wb = Text();
    if(b) {
      wb = Padding(child: wb);
    }

    children.add(wb);

@SirComputer1 DSX 提案是一个补充,目前的方式没有改变,所以如果你不喜欢它,不要使用它,继续像今天一样。

<var>只是为演示做的,因为我不想解析完整的 Dart。 最终的解决方案不包括<var> ,而是使用任何 dart 变量。 此外,'@' 仅用于演示以简化解析。 最终解决方案不包括它。

不要忘记文件中的任何其他内容都是您的正常 Dart 代码,因此您可以将其用于其他所有内容。

    var children = <Widget>[];
    if(a) {
      children.add(wa);
    }

    // You can mix and match both
    var wb = <Text/>;
    if(b) {
      wb = Padding(child: wb);
    }

    // or
    var wb = Text();
    if(b) {
      wb = <Padding> {wb} </Padding>;
    }

    children.add(wb);

    children.add(
      <Center>
          {sayHello == true ?
             <Text ['Hello, world!']/>
          :
             <Text ['Good bye']/>
          }
      </Center>
    );

让我们停止将 DSX 与当前的方式进行比较,一种不与另一种竞争。 有些人会更喜欢 JSX,这个线程是为他们准备的。 我想知道的是如何改进 DSX 以处理它无法解决的问题。

@escamoteur - 我不倾向于使用锤子作为螺丝刀。 我评估不同的技术,并为正确的用例使用正确的技术。 这并不意味着他们的事情不能在每个平台上变得更好。 :咧嘴笑:

例如; 第三方插件集成。 NativeScript 确实是所有其他跨平台的王者。 没有其他任何东西可以与 NativeScript 相提并论。 和第三方集成。 我有一个客户询问使用https://github.com/vipulasri/Timeline-View 。 Flutter 几乎是不可能的; NativeScript 给了我几个小时,它可以像任何其他 NS 控件一样工作,即使数据绑定完全有效。 另一方面,颤振具有一些强大的优势,其中 NS 标志......

使用合适的工具来完成这项工作。 :咧嘴笑:


我确实喜欢基于 XML 的屏幕布局; 但我明白为什么人们不这样做。 添加基于 XML 的构建能力并不意味着消除现有方法; 它只是互补的; 选择。 对于那些懒得看书的人,我可以在 NS 中执行与 Flutter 中相同的调用链; 但是使用 xml 的类型要少得多,而且对我来说更容易阅读。 每个人都有自己的喜好...

我实际上考虑过将基于 XML 的渲染器作为 POC 添加到 Flutter; 但我没有空闲时间。 我只是想为对话做出贡献,并说我希望看到这一进展; 但我实际上并不指望核心团队会在这方面工作。 我认为 NS XML 格式可以作为社区项目来完成,我们这些关心的人(即可能是我 :grinning :) 愿意在这些项目上进行工作。 然而,我最大的担忧@sethladd——如果我花很多时间在补丁上; 会不会因为核心团队的某个人绝对反对这个能力而被拒绝。 这就是我想在我花任何时间之前首先确定的......

@NathanaelA梦幻般的视角!!!!!!! 看我用了很多感叹号;-)你真的把它钉在了头上。

是的,我可以做 DSX,但我需要一种方法将它集成到当前的 Flutter 构建系统中,所以在我继续前进之前,我需要当前 Flutter 团队的承诺。 IDE 集成在 VS Code 上几乎是微不足道的,但在 Intellij 上则不然(除非 Google 可以访问 Intellij JSX 支持)。

@zoech ,不! 我认为这是一个问题。 我记得使用原生 Java 和 XML 开发了一个 android 应用程序。 我们仍然使用 XML 作为 UI 语言部分。 我认为将 Dart 用于逻辑和 UI 有点奇怪,而且这个问题很明显。 此外,我只希望 Google 能够将 React 的 UI 理念加入到 Flutter 中。 React 的 UI 部分非常强大和简洁。

@JonathanSum我已经看到很多关于此的评论。
对我来说,它看起来仍然是人们想要的东西,因为他们不愿意改变自己的习惯,而不是因为它对平台有利。

有些人喜欢 jsx,有些人不喜欢。 为什么不支持两种方式实现 UI。 可以写出类似jsx的语法,终于可以用flutter原生语法了,为什么不支持呢?

@zoechi

对我来说,它看起来仍然是人们想要的东西,因为他们不愿意改变自己的习惯

这是一个公平的观察,但 Flutter 成为推动者并尽可能多地消除人们(谷歌之外)采用 Flutter 的摩擦不是更好吗? 这种把关行为并没有赢得开发人员的心。

@yuu2lee4

有些人喜欢 jsx,有些人不喜欢。 为什么不支持两种方式实现 UI。 可以写出类似jsx的语法,终于可以用flutter原生语法了,为什么不支持呢?

很好的问题。 鉴于我在 DSX 上做所有工作,就像 JSX 一样, @Hixie亲自给我发了电子邮件,对进展感到兴奋,我不明白为什么不支持它,我不明白为什么不伸出手说'我有什么可以帮助你的吗? 是什么阻止你这样做?

老实说,我开始认为这个方向与前一个方向相似......这无济于事......

@cbazza

@Hixie亲自给我发了电子邮件,对进展感到兴奋..

那么您为什么不继续,其他可以提供帮助的人也应该加入并提供帮助? 如果我们不希望它像其他线程一样出现......我认为我们应该讨论什么是块,我们如何去做以及我们如何让它工作并把它放在那里......并且我还认为,flutter 和 dart 团队在某种程度上已经开始了一些工作,以减少编写 UI 的冗长性质......
也许团队现在可能无法加入,但我相信如果它是有价值的事业,我相信这对我来说是好的,无论哪种方法......他们会在某个时候赶上......所以@cbazza让我们继续你正在做并把它拿出来......就像这个家伙在早期所做的那样http://mutisya.com/尽管我不知道它的状态......我也知道@NathanaelA可以提供帮助,因为他贡献了一些Nativescript 真的很棒的东西和工具......让我们把它拿出来给更多的开发者更多的选择......

@MichaelSowah
不花更多时间在这方面的原因就像@NathanaelA所说:

然而,我最大的担忧@sethladd——如果我花很多时间在补丁上; 会不会因为核心团队的某个人绝对反对这个能力而被拒绝。 这就是我想在我花任何时间之前首先确定的......

好的,这就是我所拥有的:
(a) 一个预处理器,它接收 *.dsx 文件并输出 *.dart 文件。

这是我需要的:
(1) 有人负责“VS Code”集成。 从我的调查来看,它看起来很简单。
(2) 有人想知道如何在 Flutter 构建系统中添加预处理器功能,以便调试能够正常工作。 我的意思是代码步进将通过源映射等在 *.dsx 文件上进行。

完成上述 2 项后,我们就有了一个初始的端到端系统来让球滚动起来。 有接盘侠吗?

正如你在上面看到的,(1) 和 (2) 需要更改 Flutter 代码,Flutter 团队可以拒绝,因此如果没有支持/承诺,这个功能就会被卡住。

@cbazza太棒了,所以让我们让其中一名颤振团队成员来告诉我们他们是否愿意接受一个和两个......那么我们可以找谁来帮助我们进步......?

对于 (2) 我认为最好的办法是联系 Dart 团队,可能是通过[email protected]或他们的问题跟踪器? 我相信 Dart 2 的目标之一是创建一个基础设施来进行更多的语言实验,并让社区创建像 DSX 这样的实验。 也许@anders-sandholm @mit-mit 或@mraleph可以为您指明正确的方向。

@sethladd感谢您的快速回复,您能否也复制资源人员以及可能
飞镖团队也加入了这个线程
@cbazza您能否加入到与列出的资源人员一起进行此讨论。
关于“VS Code”集成,我敢肯定,一旦我们解决了 2 个问题, @DanTup可能有兴趣提供帮助

只是一些想法

好的,这就是我所拥有的:
(a) 一个预处理器,它接收 *.dsx 文件并输出 *.dart 文件。

这可能是您需要开始的所有内容,还有一个文件观察器可以根据更改重建 - 请参阅FileSystemEntity 。 挑战在于.dx语法是 dartlang 的超集,因此您也必须解析所有 Dart。 这会很棘手,因为与 JavaScript 不同, <>用在更多地方。 我认为 Dart 解析器已经用 Dart 编写,并且在 sdk repo 中的某个地方,但我不知道在哪里

  1. 对于 vscode 和 Intellij 的集成,它不是颤振构建系统,而是你想要的 dart分析器。 我认为您可以为此创建一个插件来消耗 dx,将其转换为 dart,然后将结果映射回原始文件。 这就是角度分析器插件如何为 html 文件提供自动完成等功能。

  2. 你想要build runner ,这是一个更复杂的包,用于a

@MichaelSowah
太好了,所以我猜你正在接受(1)和(2),所以我可以专注于转译器?

@jonahwilliams
我知道,完整的 dart 解析会很复杂,而且现在并不是真的有必要,因为我总是可以在第一次发布时使用我的标记(https://spark-heroku-dsx.herokuapp.com/index.html)

但有一点是肯定的,我们需要 IDE 和调试器正常工作,否则人们不会使用 DSX,因为代价太大。 我的意思是“使用 DSX 并忘记符号调试”,这不是一个非常引人注目的提议。 这也是我希望至少支持一个 IDE 的原因,并且 VS Code 就像馅饼一样简单(因为它已经在他们的 Typescript 和 Javascript 语法定义 json 文件中支持 JSX)

回复:IDE 和调试器,大概通过在 Dart 2 基础架构和“通用前端”中实现此功能,您应该能够使堆栈的更高级别能够感知 DSX。 我建议与 Dart 团队合作,学习如何探索通用前端及其 API 的各个部分。

@MichaelSowah我在https://github.com/flutter/flutter/issues/15922#issuecomment -376960770 中抄送了 Dart 的人

@NathanaelA您是否有兴趣加入(1)和(2),因为现在我们显然得到了团队的支持

不确定; 此刻——我被几个客户项目淹没了。 但我愿意研究如何连接到编译管道并可能创建源映射。 (即 2)但我可能需要几周的时间才能这样做。

@NathanaelA没有匆忙或任何事情,所以你很好:-)

如果DSX只是Dart + Virtual closing tag那么没有真正的好处。 dart 的一个好处是我们可以使用函数和变量来创建小部件的一部分并提高可读性。

同样使用 DSX 和预处理器,我们将失去亚秒级的热重载能力,对吗@cbazza

不,DSX 就像 JSX,与“Dart + 虚拟结束标签”完全不同,这是你今天可以用你的 Dart 小部件树和 IDE 做的事情。

此处描述了 DSX:
https://spark-heroku-dsx.herokuapp.com/index.html

DSX 是 Dart,因此您所描述的 Dart 的所有优点都在那里。 熟悉 JSX 的人会立即获得并喜欢它。

不,你不会丢失任何东西,你创建的普通 *.dart 文件没有任何变化,你仍然有亚秒级的热重载。
现在,如果您有一个 *.dsx 文件,它将首先被转换为 *.dart 并且该过程比我眨眼还快!!! 所以 DSX 用户不会注意到它。

在这个再次关闭之前,让我先说完我想说的话。
Flutter 部分的当前 UI 是一个问题,我并不是要推销 React 的想法。
因为 Flutter 的 UI 结构很难在脑海中用那些括号来实现,所以我们确实需要一些改进。 我强烈建议使用 react native 或像 React 这样的整个东西。 React 不仅使人们易于阅读,它还将庞大的 UI 代码分隔在不同的组中。 因此,我可以更快地管理庞大复杂的 UI 代码并轻松阅读它们。 另一方面,有很多带括号的树只是在颤动中,我不知道如何阅读它们。

@JonathanSum您是否尝试过带有关闭标签的最新版本的 Android Studio(3.1)?

@14n是的,我看到了那些虚拟的结束标签和评论。

一个大的类似 XML 的小部件树可能和任何其他的东西一样难以阅读,无论是 Dart、JSON、YAML 还是 JSX。 JSX 本身似乎并没有解决可读性问题。

使用当前语法读取大小合理的小部件树没有任何问题。 此外,Flutter 促进了组合,因此一旦某个小部件变得太大,将其拆分为多个较小的小部件是微不足道的。

对提议的 DSX 格式的主观意见:

  1. 视觉上并没有真正的好处 - 阅读大型 XML-tree 可能会很痛苦,所以它似乎不能解决问题。 例如,促进清洁代码实践实际上会解决可读性问题,但这些实践可以应用于(几乎)任何语法。
  2. 需要学习另一种 DSL/语法。 我真的非常喜欢我只需要知道一种语法 - Dart - 就可以做所有事情 - 布局、样式、动画、逻辑。 与使用 html/js/jsx/ts/coffee/css/sass/scss 的 Web 发生的事情相比,它对新手和经验丰富的开发人员都更加友好。 事实上,我什至认为这是 Flutter 相对于其他平台的主要优势。

也就是说,我相信 Dart 有改进的余地,以便在用于描述 UI 时更具表现力,尽管我更希望它更多地是对现有 Dart 语法的扩展,而不是全新的 DSL。

请停止试图让 Flutter 成为“热门新事物”。 它本身就是热门的新事物,让它探索新的范式。

@naiveaiguy我觉得很热。 它使我的工作效率很高,并允许我与浏览器和服务器应用程序共享代码。
一个夏天我不需要炒作。 我需要一些能让我完成工作的东西。
这正是 Flutter 和 Dart 所做的。

我对这面镜子的看法是@pulyaevskiyhttps://github.com/flutter/flutter/issues/15922#issuecomment -377666972 中所说的。 我看到的所有不那么可读的示例通常可以在现有代码中整理,我认为可能会对 Dart 进行更多小的更改(类似于删除 new/const),可以进一步改进它. 使用完全不同的语法和一套全新的工具代码维护一整套其他文件似乎是一项高成本,而我认为收益相对较小(FWIW,我也更喜欢没有 JSX 的 React)。

我不知道它是否在这里完全适用,因为提议的 dsx 也允许正常的 Dart 代码,但每次我听到有人谈论一种新语法时,我都会想起 Gilad A DOMain of Shadows的这篇好文章。 这些事情总是比人们想象的要复杂。 它不像只是转换代码那么简单,因为人们会期待实时错误、代码完成、重构、工具提示等——这是一项艰巨的任务。

而不是一个工作的编译器,我更感兴趣的是看到一些被认为难以阅读的代码之间的三向比较,它在这个提议的语法中的外观,以及如果你可以对它进行任何更改它会是什么样子现有的 Dart 语法,无需替换所有括号。 例如,我在 React 中喜欢的一点是孩子作为最后一个参数作为可变参数传递 - 我认为childchildren在 Flutter 中添加了很多噪音 - 也许那里还有改进的空间. 还有一些关于更改格式或突出显示 Widget 类名称是否有帮助的讨论。 看起来Extract Widget重构正在轻松分解大型构建方法。 当然,IntelliJ 有 Flutter Outline 视图,让您可以在树中查看代码,并且选择与编辑器中的光标位置保持同步(我真的希望在 VS Code 中得到类似的东西,尽管它被阻止了通过像这样的一些 VS Code 功能,请随意 👍!)。

@pulyaevskiy
我明白你在说什么,但实验是好的,它是进化的道路。 即使我对 DSX 的实验失败了,我希望其他人能尝试许多其他的东西,并汇集最好的想法来创造惊人的技术。

@sethladd
谢谢你的线索。
很想收到@anders-sandholm @mit-mit 或@mraleph的回复
如何使用 Dart 2 基础设施和“通用前端”。
我将与@NathanaelA 一起调查。

@DanTup

这些事情总是比人们想象的要复杂。 它不像只是转换代码那么简单,因为人们会期待实时错误、代码完成、重构、工具提示等——这是一项艰巨的任务。

是的,你是对的。 我的“琐碎、简单的实现”评论仅适用于让编辑器识别 .dsx 语法。 我查看了 Intellij,他们需要一个完整的语言解析器(所以这很复杂),而 VS Code 使用语法文件要容易得多,而且我还注意到 Typescript/Javascript 语法文件已经支持 JSX(而 DSX 只有JSX 的微小变化)。

我们肯定会向您寻求帮助/指导以进行我们的实验。

总之,我有:
(a) 一个预处理器,它接收 *.dsx 文件并输出 *.dart 文件。
https://spark-heroku-dsx.herokuapp.com/index.html

我需要帮助:
(1) 有人负责“VS Code”集成。
(2) 有人想知道如何在 Flutter 构建系统中添加预处理器功能,以便调试能够正常工作。 我的意思是代码步进将通过源映射等在 *.dsx 文件上进行。

@NathanaelA将帮助解决(2)。

所以我还在找人帮忙 (1)
有接盘侠吗? @birkir @yuriy-manifold @tehfailsafe @alexkrolick @sanketsahusoft

@DanTup - 我不是 JSX 专家,但我可以谈论 NativeScript XML 格式。 我可以:

StackLayout 类支持的任何属性都可以添加到 XML。 所以这是一对一的关系; 这消除了大量额外的麻烦:所以让我们看一下 Flutter 演示:
https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/gallery/home.dart#L39 -L63

<AnimationBuilder animation="{{animation}}">
   <Stack>
      <BackgroundLayer top="{{-layer.parallaxTween.evaluate(animation)}}" left=0.0 right=0.0 bottom=0.0>
          <Image src="{{layer.assetName}}" package="{{layer.assetPackage}} fit="cover" height="{{maxHeight}"}/>
      </BackgroundLayer>
   </Stack>
</AnimationBuilder>

如果我正确转换它,我发现这更容易阅读和理解。 :咧嘴笑:

@NathanaelA如果您需要做一些更动态的事情,比如调用map会发生什么? 这是来自同一文件的一些代码:

  Widget build(BuildContext context) {
    return new AnimatedBuilder(
      animation: animation,
      builder: (BuildContext context, Widget child) {
        return new Stack(
          children: _kBackgroundLayers.map((_BackgroundLayer layer) {
            return new Positioned(
              top: -layer.parallaxTween.evaluate(animation),
              left: 0.0,
              right: 0.0,
              bottom: 0.0,
              child: new Image.asset(
                layer.assetName,
                package: layer.assetPackage,
                fit: BoxFit.cover,
                height: _kFlexibleSpaceMaxHeight
              )
            );
          }).toList()
        );
      }
    );
  }

children: _kBackgroundLayers.map(...)在这种语法中会是什么样子?

JSX/DSX 仅将标记转换指定为:

在:
<A property="a"/>
出去:
new A(property: a)

在:

<A property="a">
  <B/>
  <C/>
</A>

出去:

new A(property: a, 
children: <Widget>[
   new B(), 
   new C()
])

并且您可以使用 {} 放置任何有效的 Dart 代码,例如变量评估和匿名函数等。{} 可以放置在 3 个位置。 下面的示例显示 {} 在 2 个位置(标记属性和作为子项)中使用,第 3 个位置与展开运算符一起使用。

  Widget build(BuildContext context) {
    return <AnimatedBuilder
      animation={animation}
      builder={(BuildContext context, Widget child) {
        return <Stack> {
          _kBackgroundLayers.map((_BackgroundLayer layer) {
            return <Positioned
              top={-layer.parallaxTween.evaluate(animation)}
              left={0.0}
              right={0.0}
              bottom={0.0}>
              <Image.asset [layer.assetName]
                package={layer.assetPackage}
                fit={BoxFit.cover}
                height={_kFlexibleSpaceMaxHeight}
              />
            </Positioned>;
          }).toList()
        } </Stack>;
      }}
    />;
  }

把上面的代码放到一个Javascript文件中,用VS Code/Intellij查看。 请注意可用于打开和折叠 XML 节点以使树更小/更大的 +/-(行的左侧)。

为什么我们不能承认问题并采用 React Native 方式? 我们会这样做还是不这样做?

@JonathanSum很抱歉被引导到这里,但你认为你是谁? 没有一般问题,只是您不喜欢的东西。
你甚至用 Flutter 写过一个 App 吗?
上面混合 Dart 和 XML 的例子看起来比 Dart 差得多。 在这里没有任何收获。
我来自使用 xaml 的 Xamarin Forms,我非常喜欢它。 但我没有抱怨为什么 Flutter 不支持 Xaml,而是直接投入其中并开始适应和学习。
如果你想像在 React 中一样工作,那就面对它,然后使用 Reactive 而不是在这里惹恼所有人。

这是与上面相同的代码块,但在纯 Dart 中并进行了重构以避免深度嵌套。
好奇以下片段的哪些部分难以阅读和/或理解?

Widget build(BuildContext context) =>
    AnimatedBuilder(animation: animation, builder: _buildChild);

_buildChild(BuildContext context, Widget child) {
  return Stack(
    children: _kBackgroundLayers.map((_BackgroundLayer layer) {
      final image = Image.asset(layer.assetName,
          package: layer.assetPackage,
          fit: BoxFit.cover,
          height: _kFlexibleSpaceMaxHeight);
      return Positioned(
          top: -layer.parallaxTween.evaluate(animation),
          left: 0.0,
          right: 0.0,
          bottom: 0.0,
          child: image);
    }).toList(),
  );
}

事实上,我个人会让它看起来更接近这样的东西:

Widget build(BuildContext context) => AnimatedBuilder(
      animation: animation,
      builder: _buildChild,
    );

_buildChild(BuildContext context, Widget child) {
  return Stack(
    children: _kBackgroundLayers.map(_imageForLayer).toList(),
  );
}

_imageForLayer(_BackgroundLayer layer) {
  final top = -layer.parallaxTween.evaluate(animation);
  final image = Image.asset(
    layer.assetName,
    package: layer.assetPackage,
    fit: BoxFit.cover,
    height: _kFlexibleSpaceMaxHeight,
  );
  return PositionedImage(top: top, image: image);
}

class PositionedImage extends StatelessWidget {
  PositionedImage({this.top, this.image});
  final double top;
  final Image image;

  <strong i="10">@override</strong>
  Widget build(BuildContext context) =>
      Positioned(top: top, left: 0.0, right: 0.0, bottom: 0.0, child: image);
}

同样,我们似乎在这里混合了两个不同的问题:

  1. 不喜欢 Dart 语法,需要类似 XML/JSX 的语法
  2. Flutter 代码的可读性。

这里有没有人相信实现 JSX 会解决可读性问题? 仍然可以在代码中创建深度嵌套的树,开发人员仍然需要完成我刚刚使用 Dart 版本执行的相同步骤以使内容可读。

但它肯定会增加一个额外的构建/转换步骤,包括源映射和 co,以及在 IDE 和 Dart SDK(分析器、调试器等)中支持这种基础设施的大量工作。

@JonathanSum @escamoteur我们不会在这个项目上咄咄逼人。 请保持协同合作。 谢谢。 最近的讨论是友好而富有成效的,因此感谢参与讨论的每个人!

总的来说,在我看来,添加 DSX 会在 Flutter 生态系统的早期阶段分裂,需要做很多工作来尝试保持两种语法的功能完整,在大多数情况下实际上并不能显着提高可读性,并吸引那些喜欢纯粹因为与热门新事物具有相似的语法和/或范式而被项目吸引。

@Hixie对不起,我发脾气了,但我认为 Flutter 的发展势头很好,而且 Flutter 开发人员在没有这样的要求的情况下有足够的工作要做

@escmoteur - 我认为这就是为什么我特别说“社区”努力。 除了他们愿意接受补丁之外,我认为这不需要涉及 Flutter 核心团队……Seth 似乎说过我们能够继续进行。 如果您对此功能不感兴趣; 然后不要使用它... :grinning:

@escamoteur ,我为我所说的方式感到抱歉。
我从教程中构建了一些颤振应用程序。 我对颤动的所有感觉是一切都是对象而不是小部件。 它就像一大块复杂的面向对象的编程代码无序地粘在一起。

我认为最重要的是做一个易于阅读和管理的框架,它不应该太复杂。 最重要的是,我认为 React-Native 的构建方式遵循人类自然构建的方式。 另一方面,flutter需要把有状态的widget连接到无状态的widget中......而且我们这些年使用的UI框架大部分都以这种React方式为标准,我认为flutter应该更多地关注这一点而不是热重载(当我尝试添加新的一些新类时,控制台告诉我重新启动一切而不是热重载)。 我真的认为这是一个问题,而不是评论或要求。
naiveaiguy 说:

请停止试图让 Flutter 成为“热门新事物”。 它本身就是热门的新事物,让它探索新的范式。

你可以去看看他们。
https://facebook.github.io/react-native/
React 中的思考:
https://reactjs.org/docs/design-principles.html
扑:
https://flutter.io/tutorials/animation/

看看 React-Native,它甚至把状态管理放在上面,把 UI 部分放在下面。 这是人类的艺术和自然行为。 这就是学习曲线和管理时间很短的原因。 因此,请不要将 XML 甚至 Xamarin 与 React Native 进行比较。 而且,futter只是一种混乱和无序。 无状态连接到有状态,创建状态连接无状态中的所有内容。 使用 React-Native,你正在用铅笔画一幅美丽的图画。 用颤振,就像在纸上滴一滴水,然后将水分成不同的部分。 但我认为我们仍处于 Flutter 的早期阶段。 React-Native 有自己的理念和目标,而 Flutter 只是一个严肃的项目,要不然大家不同意我的观点。

@JonathanSum

我从教程中构建了一些颤振应用程序。 我对颤动的所有感觉是一切都是对象而不是小部件。 它就像一大块复杂的面向对象的编程代码无序地粘在一起。

你没有提供一个理由,为什么你对这件事的主观感受会证明它不可避免地会造成大量的分裂。 在这两种方法之间,客观上没有一种比另一种更好,我认为这不值得,而且绝对不是 Flutter 现在作为一个生态系统所处的阶段。

我认为最重要的是做一个易于阅读和管理的框架,它不应该太复杂。

这是一个重言式。 显然每个人都想要这个,但是人们有不同的方法来解决这个问题。 Flutter 的范式就是其中之一。

最重要的是,我认为 React-Native 的构建方式遵循人类自然构建的方式。

我不认为像构建 UI 的语法这样次要的事情会影响框架的整体易用性。

另一方面,颤振需要将有状态的小部件连接到无状态的...

您似乎根本不同意 Flutter 处理应用程序的方式。 你为什么用它? 此外,这不是一个有效的观点。 你不是在表达你认为错误的东西,你只是在说“我认为无状态和有状态小部件之间的连接是错误的,并且以某种模糊的方式复杂,我不会继续解释。”

而且,我们这些年使用的大部分 UI 框架都以这种 React 方式为标准,

争论广告大众。

我认为颤振应该更多地关注这一点而不是热重载(当我尝试添加新的一些新类时,控制台告诉我重新启动一切而不是热重载)

是的,因为热重载并不是像 Flutter 那样容易实现的功能。 我认为 Flutter 成功实现的开发周期,即使是在 30-40% 的代码更改中,也确实令人印象深刻,并且只会因转译层而减慢。

然而,futter就像只是混乱和无序。

在这里,您已经明确表示您根本不喜欢 Flutter 的方法。 那就别用了。 如果你认为改变 UI 语法会以某种方式神奇地使 Flutter 不再“混乱和无序”,那么你需要提供明确的证据证明在 Flutter 所使用的相同类型的设置和约束下工作。

这就是为什么学习曲线和管理它的时间很短的原因。 请不要将 XML 甚至 Xamarin 与 React Native 进行比较。

很公平 - 那就使用 React Native。 那里的开发人员在他们的范例方面做得很好。

无状态连接到有状态并在无状态中创建状态

什么? 不,这完全是错误的——你的意思是什么?

使用 React-Native,你正在用铅笔画一幅画。 轻轻一颤,就好像一滴水滴在纸上,把水分成不同的部分。

坦率地说,这个类比对我来说意义不大。 我可以很容易地说出相反的意见,我们就会回到我们从这里开始的地方。

你表现得好像这是不言而喻的(“让我们面对现实吧”),我们只是在自命不凡和/或无法忍受地说 Flutter 团队不应该处理这个问题。 如果您希望其他人认真对待您,这不是一个好的态度。

补充一点:请不要假装这是第三方开发人员可以在没有任何参与或不参与 Flutter 核心团队的情况下完成的事情。 Flutter 团队将不得不在 IDE 和编辑器插件、宣传和处理 GitHub 问题上做很多额外的工作,如果这样的功能要作为 Flutter 的和谐部分得到令人满意的实现。

@naiveaiguy
好吧,我认为你是对的。 我只是一个随机比较这里的每个人和一个喜欢 React 的人。 Flutter 有自己的方式,React 也有。 我为我的态度感到抱歉,我不是很好。

@JonathanSum我认为您只需要更多时间来真正了解 Flutter 应用程序的构建方式。 公平地说,关于架构、如何正确使用继承的小部件以及如何将您的视图模型连接到小部件的文档并不多。

我想知道的是你为什么对 Flutter 感兴趣? 对我来说 React 是不行的,因为 JS

这么多评论,这么少时间,也许我应该集中精力......

@escamoteur你到底是什么意思:

对我来说 React 是不行的,因为 JS

ES6/7 或 Typescript 与 Dart/Kotlin/Swift 非常接近,我会很高兴与这些女士中的任何一个跳舞 :)

Flutter 吸引我的地方是图形和动画支持。 Direct Skia Vector 图形构建在 OpenGL 之上,可实现 60fps 的超快速 UX,轻松实现您所看到的内容:
https://uimovement.com/
我喜欢自定义 UX,而 Flutter 可以做到这一点。 几十年来我已经实现了 UX 的东西,我真的很喜欢能够使用声明式/反应式技术来构建它,Flutter 支持这一点。

@pulyaevskiy

同样,我们似乎在这里混合了两个不同的问题:

  • 不喜欢 Dart 语法,需要类似 XML/JSX 的语法
  • Flutter 代码的可读性。

正确,这里的这张票(和上一张)只需要类似 JSX 的功能。 还有其他改进 Dart 语言的门票,以减少当前 UI 构建代码的冗长。

这里有没有人相信实现 JSX 会解决可读性问题?

这可能对他们来说,对他们自己来说。

是的,您提供的示例使树更小,但是通过将其分成几部分并将其移动到其他地方,这也使得在代码中查看整个结构变得更加困难。 我宁愿将完整的结构保留在一个地方,并从树中取出一些相关的属性(命名参数)并使用 DSX 的扩展运算符将它们带入。只是我的偏好。

但它肯定会增加一个额外的构建/转换步骤,包括源映射和 co,以及在 IDE 和 Dart SDK(分析器、调试器等)中支持这种基础设施的大量工作。

我们正在处理这个问题, @sethladd已经声明I believe one of the goals of Dart 2 was to create an infrastructure for more experimentation with the language and let the community create experiments like DSX.

@naiveaiguy

我认为 Flutter 成功实现的开发周期,即使是在 30-40% 的代码更改中,也确实令人印象深刻,并且只会因转译层而减慢。

是的,我真的很喜欢热加载,尽管它并非一直都有效。 我肯定会接受,但是您对转译减慢速度的评论是毫无根据的。 如果您不使用 DSX,它不会在您的编译时间中添加任何内容。 如果您使用 DSX,转译器非常快,您甚至都不会注意到它。

补充一点:请不要假装这是第三方开发人员可以在没有任何参与或不参与 Flutter 核心团队的情况下完成的事情。 Flutter 团队将不得不在 IDE 和编辑器插件、宣传和处理 GitHub 问题上做很多额外的工作,如果这样的功能要作为 Flutter 的和谐部分得到令人满意的实现。

并不真地。 我们正在这样做,只是要求不要被阻止。 我们正在寻求指导,为我们指明正确的方向。 我不会自己做所有这些,所以现在我们有 2 个人(谢谢@NathanaelA),如果他们想提供帮助,我们正在寻找更多的人(至少还有 1 个人)。

大家好! 首先,我想指出,在这个问题上继续来回讨论没有多大意义——由于线性结构,它会变得很大而且很难理解。 您的论点将丢失并一遍又一遍地重复。 让我们将其简化为纯数字:

  • 如果您支持此功能 - 竖起大拇指对此问题的第一条评论。
  • 如果您反对此功能 - 请拒绝对此问题的第一条评论。

接下来,我想澄清@sethladd的声明,它应该是_“Dart 2 的目标之一是为 Dart 团队的语言创建更多实验的基础设施”_。

即使在 Dart 2 中,我们也没有提供任何 API,可以让您轻松更改 Dart 语言的语法,而无需重新构建 Dart SDK(或 Flutter 引擎工件)。 Dart 2 提供的是一个 _common front-end_ (CFE) 基础设施(位于 Dart SDK 源代码中的pkg/front_end中)——它是一个用 Dart 编写的 Dart 语言解析器。 对于像 DSX 这样的纯语法糖语言更改,您应该能够只编辑 CFE 代码、构建 Dart SDK(或 Flutter 引擎)并让所有工具(除了内置在相应 IDE 插件中的语法突出显示代码)来选择您的新语法扩展。 请注意,目前只有 VM 和 dart2js 实际使用 CFE,analyzer 计划接下来进行转换。 正如你所看到的,这里有一定的进入门槛。

这里要强调的重要一点是,由于没有扩展 Dart 语法的 API,您必须与 Dart 语言团队合作才能扩展语言。 目前还没有正式的流程,但是对于像 DSX 这样的功能,需要大量的证据和动机才能将其包含到 Dart 中。 (/ fyi @leafpetersen @lrhn - 如果我错了,请纠正我)

以下是我对类似 DSX 的解决方案的支持者的建议:

  • 首先,您实际上需要以书面形式提出您的建议,并将讨论转移到促进非线性讨论的地方。 当您提出语言更改时,您需要详细描述您要解决的问题以及如何使用您提出的语法扩展来解决它。 否则,就不可能评估提议变更的成本和收益。 然后你需要一种方法来对提案的不同部分进行非线性讨论,例如

    • 如果您将提案放入 Google Doc,那么人们可以使用内置评论来讨论您提案的各个组成部分;
    • 或者,您可以创建一个 GitHub 存储库,其中包含您的提案的降价描述,并使用 GitHub 问题和 PR 来完善和讨论您的提案。

    请注意,我并不是说您需要为您的更改提出_正式规范_,以便在细化级别上与 Dart 语言规范相媲美。 相反,您需要有大量示例来说明提议的变更如何发挥作用以及它提供了什么好处。


  • 接下来,如果可以的话,您应该尝试实现。 即使有 CFE 基础设施,这里的障碍也很高——但比以前低得多。

@mraleph我认为关于集成到 Dart 的争论更多的是关于调用代码生成或类似的钩子,而不是改变语言。
我不知道这样的事情是必要的。
我认为这主要可以像 Angular 的 Analyzer 插件一样实现,只是 DSX 而不是 HTML

@mraleph

非常感谢您的澄清。
我们真的不想修改 Dart 语言,我们需要的是预处理能力,以便将我们的实验性 DSX 转换为 Dart。
顺便说一句,您可以在线尝试:
https://spark-heroku-dsx.herokuapp.com/index.html

问题是当 Dart 首次出现时,它能够转换为 Javascript,并且通过使用源映射,它能够插入到 Javascript 生态系统中(其他几种语言也这样做:Coffeescript、Typescript 等)。 我们正在寻找与 Dart/Flutter 类似的东西。 我们正在寻找通用的预处理功能,它可以使任何其他转译语言能够构建在 Dart/Flutter 之上。

关于投票,之前的票有一些数字:
https://github.com/flutter/flutter/issues/11609

@cbazza

我们真的不想修改 Dart 语言,我们需要的是预处理能力,以便将我们的实验性 DSX 转换为 Dart。

我说的是*.dsx文件实际上是 Dart 文件,您可以在其中使用一些额外的语法。 正如我所说,目前没有 API 或扩展点可以促进创建此类语法扩展,从而允许这些语法扩展与 Dart 生态系统中的所有工具透明地互操作。 此外,我认为目前还没有任何设计和提供此类 API 或扩展点的计划——因此,目前最好的选择是分叉 Dart SDK 并将 DSX 支持内置到 CFE 中。

我还建议考虑极端案例——而不是考虑简单案例。 例如,假设您正在编辑 DSX 文件。 在这种情况下,您很可能希望看到半完成代码的实时完成,例如构造函数名称和属性名称。 这将如何与源映射一起工作? 诸如此类的事情构成了开发人员的经验。

@mraleph再次感谢您。

我们的目标无疑是为 DSX 用户提供出色的用户体验。

有些人喜欢类似 XML 的语法,有些人讨厌它。也许添加类似 jsx 的语法太过分了。我对 Flutter 的主要关注是可读性。恕我直言,Dart 和 Flutter 的当前语法仍有改进的空间(对我来说是主要是关于深嵌套括号, childchildren ,分号噪音等)
在这里重新发布一些示例代码[1],

// Comparing Flutter to what it might look like in Kotlin
class TutorialHome : StatelessWidget {
    override
    fun build(context: BuildContext) = scaffold {
        appBar = appBar {
            leading = iconButton {
                iconImage = Icon(Icons.menu)
                tooltip = "Navigation menu"
                onPressed = null
            } 
            titleText = "Example title"
            actions = [ // based on https://twitter.com/abreslav/status/867714627060322305
              iconButton { 
                iconImage = Icon(Icons.search)
                tooltip = "Search"
                onPressed = null  
              }
            ]
        }
        body = center {
            // Remember: This is a fully functional programming environment. You can execute any 
           //  code you can think of.
            child = Text("Hello ${MyApp.users.me.fullName.split(" ").first}!")
        }
        floatingActionButton = fab {
            tooltip = "Add"
            childImage = Icon(Icons.add)
            onPressed = null
        }
    }
}

Dart 2 版本,带有new和可选分号(来自@sethladd 的代码)[2],

class TutorialHome extends StatelessWidget {
  <strong i="13">@override</strong>
  Widget build(BuildContext context) => Scaffold(// implicit new!, also matching your Kotlin here
      appBar: AppBar(
        leading: IconButton(
          icon: Icon(Icons.menu)
          tooltip: 'Navigation menu'
          onPressed: null
        )
        title: Text('Example title')
        actions: [ // Dart + strong mode will infer the contents of the list
          IconButton(
            icon: Icon(Icons.search)
            tooltip: 'Search'
            onPressed: null
          )
        ]
      )
      // body is the majority of the screen.
      body: Center(
        child: Text('Hello, world!')
      )
      floatingActionButton: FloatingActionButton(
        tooltip: 'Add' // used by assistive technologies
        child: Icon(Icons.add)
        onPressed: null
      )
   )
}

IMO,kotlin 版本干净,看起来更好。Dart 2 版本非常接近,仍有改进空间(如果 Dart 支持扩展方法?)。 所以我认为改进 Dart 语法以减少冗长是正确的方向。

[1] https://gist.github.com/asarazan/b3c23bef49cf9a61f5a1a19de746f1b0
[2] https://gist.github.com/sethladd/7397a067deb43b6052032195fcb26d94

另一个角度,我喜欢 JSX 的 compose 能力。

使用组件(小部件)非常容易且易于访问,在编辑器中上下移动它们只是键盘快捷键(Alt+UP / Alt+DOWN)的问题。 在将东西移入和移出容器、行、列等时尤其如此。

但这不是 DSX 自己解决的问题。 他们自己需要的小部件
更受限制的属性命名才能正常工作。 在 React 中,这是一个名为children的属性,是 JSX 中的主要主体。 Flutter 允许灵活地为孩子命名(孩子、孩子、身体等)。

这是对赞成和反对的一个很好的讨论: https ://github.com/jsforum/jsforum/issues/1

DSX

来源: https ://github.com/flutter/flutter/blob/master/examples/platform_view/lib/main.dart

我不得不承认 DSX 样本看起来很吸引人。 但是我担心一旦你将它与 Dart 代码混合使用,例如当使用任何构建器小部件时,它看起来会非常难看。

@birkir DSX 应该能够支持诸如多个/非children子插槽的渲染道具模式之类的东西。 如果它可以将函数或类引用作为道具(它可能会自动),它将开箱即用。

就工具实现而言,Javascript 工具长期以来一直支持非标准语法和语言扩展(Flowtype/Typescript/Babel),因此 JSX 的许多工具都利用了现有的转译器。 Afaik Dart 还没有经历过这种程度的碎片化,因此该工具还不存在。 但现在是开始构建它的好时机😄

恕我直言,类似 json 的语法比 ~xml-like~ 语法好得多!

container {
  padding: EdgeInsets.symmetric { vertical: 16.0  }
}

@jaychang0917
我不认为 JSX 可以与 XML 相提并论。 我认为 JSX 和 XML 作为超音速飞机和螺旋桨飞机是两个不同的东西。

使用 JSX,您可以执行以下操作:

<supersonicAircarft 
          aircarft={{"F-22"}} 
          speed={{"mach2"}} 
          style={{"you can style it whatever you want as simple as css"}}
/>

要么

<Image
          source={{uri: 'https://i.chzbgr.com/full/7345954048/h7E2C65F9/'}}
          style={{width: 320, height:180}}
        />

使用 JSX,我们甚至可以像上面那样将所有内容逐个分解,或者您可以将大部分 UI 组合到一个 <> 标记中,以便将这大部分 UI 放在您想要的任何位置。

这就是为什么 React 取代了 HTML 和 XML 并采用 JSX 来构建 iPhone 应用程序或 Web 应用程序,或者人们说 JSX 只是 HTML 的一个更酷的版本。

  • 我不喜欢 XML 和 HTML,但喜欢 JSX。
  • 我认为最重要的不是 iPhone 与台式机的性能。

  • 最重要的是易于用作 iPhone 与桌面。

例如:

import React, { Component } from 'react';
import { Image, ScrollView, Text } from 'react-native';

class AwkwardScrollingImageWithText extends Component {
  render() {
    return (
      <ScrollView>
        <Image
          source={{uri: 'https://i.chzbgr.com/full/7345954048/h7E2C65F9/'}}
          style={{width: 320, height:180}}
        />
        <Text>
                        JSX is the philosophy, everything is a component. Simple is Complicate because you can 
                        form everything to your own perfect shape. 
        </Text>
      </ScrollView>
    );
  }
}

或写

< AwkwardScrollingImage/>

一次编写,到处运行

import { AwkwardScrollingImage } from './your-native-code';
class SomethingFast extends Component {
  render() {
    return (
      <View>
          <AwkwardScrollingImage/>
        <Text>
            JSX is the philosophy, everything is a component. Simple is Complicate because you can form everything to your own perfect shape. Everything is a widget or component.
        </Text>
      </View>
    );
  }
}

~Flutter 正在使用一种编程语言来构建 UI。 ~

参考:

扑:
https://flutter.io/tutorials/layout/
构建 android、Iphone 甚至桌面的 React Native:
https://facebook.github.io/react-native/

@birkir
哦,看起来太棒了! 只有肉没有骨头:)
想象一下使用https://builderx.io/ (看看第二张动画图像 - 像 Flex 一样的 2 种 UI 构建方式:)

@escamoteur
使用内联构建器,它看起来和当前的方式一样混乱; 上面提供了样品:
https://github.com/flutter/flutter/issues/15922#issuecomment -377780062

无论如何,我认为目前的方式是明确和一致的。 在一个dart 文件中混合一些 dart 代码和<标签让我觉得代码很尴尬和不清楚。 从 android 开发人员的角度来看,这看起来像是在布局 xml 文件中编写 java/kotlin 代码:)

只是我的两分钱

@JonathanSum嗯...

那么使用 JSX 的哪些优势是当前的 Flutter 方式无法做到的呢? 我没有看到你说的任何论据是强有力的。

JSX 不像 XML。 JSX 比 XML 更简单、更强大。

顺便说一句, JSX 类似于 xml ,如果 facebook 团队没有对我撒谎:)

@jaychang0917
JSX 不是 XML,因为 JSX 比 XML 更简单、更强大。(我说 JSX 不像 XML)

如果你说没有强有力的论据,让我问你一个问题。
让我在这里结束我的谈话。 如果人们想要 JSX 或 DSX 什么的,将来会有类似的。

  • 参考:
    https://facebook.github.io/jsx/
    This specification does not attempt to comply with any XML or HTML specification. JSX is designed as an ECMAScript feature and the similarity to XML is only for familiarity.

我确实错过了 XML 中真正的结束标签:)
想法:自动生成的结束标签

Kotlin 也可以解决这个问题。 看看Kotlin-reactAnko有多棒

Kotlin-react 不是那么棒,KSX 会更好:)

import React from 'react';

export function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
package hello

import react.*
import react.dom.*

fun RBuilder.hello(name: String) {
    h1 {
        +"Hello, $name"
    }
}
package hello

import react.*
import react.dom.*

fun RBuilder.hello(name: String) {
   <h1>Hello, {name}</h1>
}

标签只是不属于那里:)

在 JSX/DSX/KSX 阵营中,我当然相信标签属于代码 :)

@saied89
您想使用标签将元素嵌套在另一个元素中,就像 HTML 一样? 或者您想输入单词“children”、“child”还是 [ ]? 此外,JSX 确实提供了只需输入一个标签即可重用数百个 UI 代码的功能。

也许另一方面是dart format所做的默认格式。 恕我直言,尤其是领头的孩子很难阅读:/children。

我真的更喜欢一些强调树结构的格式:

 Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: new Text("WeatherDemo")),
      resizeToAvoidBottomPadding: false,
      body: 
        new Column(children: <Widget>
        [
          new Padding(
            padding: const EdgeInsets.all(16.0),
            child: 
            new TextField(
                    key: AppKeys.textField,
                    autocorrect: false,
                    controller: _controller,
                    decoration: new InputDecoration(hintText: "Filter cities",),
                    style:  TextStyle(fontSize: 20.0,),
                    onChanged: ModelProvider.of(context).textChangedCommand,
                    ),
          ),
          new Expanded(
                child: 
                new RxLoader<List<WeatherEntry>>(
                        key: AppKeys.loadingSpinner,
                        radius: 25.0,
                        commandResults: ModelProvider.of(context).updateWeatherCommand,
                        dataBuilder: (context, data) => new WeatherListView(data ,key: AppKeys.weatherList),
                        ),
          ),
          new Padding(
            padding: const EdgeInsets.all(8.0),
            child: 
            new Row(children: <Widget>
            [
                new Expanded(
                    child: 
                    // This might be solved with a Streambuilder to but it should show `WidgetSelector`
                    new WidgetSelector(
                            buildEvents: ModelProvider.of(context).updateWeatherCommand.canExecute,   //We access our ViewModel through the inherited Widget
                            onTrue:  new RaisedButton(    
                                            key: AppKeys.updateButtonEnabled,                           
                                            child: new Text("Update"), 
                                            onPressed: ModelProvider.of(context).updateWeatherCommand,
                                            ),
                            onFalse:  new RaisedButton(                               
                                            key: AppKeys.updateButtonDisabled,                           
                                            child: new Text("Please Wait"), 
                                            onPressed: null,
                                            ),

                        ),
                ),
                new StateFullSwitch(
                        state: true,
                        onChanged: ModelProvider.of(context).switchChangedCommand,
                   )
              ],
            ),
          ),
        ],
      ),
    );
  }

这可能不是理想的解决方案,但它应该指明方向。
@sethladd有机会朝那个方向做点什么吗?

首先,我很高兴这没有像它的姊妹问题那样激烈:微笑:。

如果我被要求选择两种语法中的任何一种,我会倾向于 Dart 方面。 这是基于几个事实:

  • 我更喜欢在尽可能少的上下文之间切换。 不管你喜不喜欢,在语法之间跳转是一种方法。 这可以通过工具支持得到帮助,但这会导致以下几点。
  • 我更喜欢开发团队将时间花在阻止我们编写某些功能和/或阻止人们跳入 Flutter 的其他问题上。 我认为没有类似 JSX 的语法不应该是公司/开发人员/任何人拒绝 Flutter 的原因。
  • 我们将从每次 Dart 更新中受益。 这对 Dart 来说尤其如此,因为 Flutter 是它的主要客户之一,而且它是一个 UI 框架。 例如,请参阅new/const更改。
  • 我高度重视类型安全。 并不是说类似 JSX 的语法不能是类型安全的,我不相信为实现它所付出的努力值得它的收入。

除此之外,我实际上更喜欢类似 Kotlin 的语法。 特别是如果所说的语法为 Dart 带来了一些 Kotlin 特性:无辜:。

@emalamela

事情就是这样,没有你所说的上下文切换,只需询问任何经验丰富的 React 开发人员即可。 此外,这种语法分离实际上是一个很棒的功能,因为当您查看代码时,您可以很容易地看到什么是声明式的,什么是命令式的。

我认为没有类似 JSX 的语法不应该是公司/开发人员/任何人拒绝 Flutter 的原因。

但不幸的是,它适用于许多 React 开发人员。

我们将从每次 Dart 更新中受益。

我看不出 DSX 是如何从 Dart 更新中受益的,因为它是 Dart 的超集。

我高度重视类型安全。 并不是说类似 JSX 的语法不能是类型安全的,我不相信为实现它所付出的努力值得它的收入。

在 DSX 中实现类型安全的努力是零,因为 DSX 只是 Dart 之上的一个微小的语法糖层,所以它使用 Dart 类型系统就像它使用 Dart 控制语句等一样。
https://github.com/flutter/flutter/issues/15922#issuecomment -377780062

感谢您的意见@cbazza

事情就是这样,没有你所说的上下文切换,只需询问任何经验丰富的 React 开发人员即可。

我不是经验丰富的 React 开发人员,所以对我来说这是一个上下文切换。 就像在 Android 中一样,您必须从 Java/Kotlin 跳转到 XML,尽管那里的跳转更大。 一种语言,相同的工具,更少的开销。

此外,这种语法分离实际上是一个很棒的功能,因为当您查看代码时,您可以很容易地看到什么是声明式的,什么是命令式的。

在我看来,现在的方式非常具有声明性。

我看不出 DSX 是如何从 Dart 更新中受益的,因为它是 Dart 的超集。
在 DSX 中实现类型安全的努力是零,因为 DSX 只是 Dart 之上的一个微小的语法糖层,所以它使用 Dart 类型系统就像它使用 Dart 控制语句等一样。

公平点。 但是 DSX 仍然需要维护和改进,这仍然意味着我希望看到的努力集中在生态系统的其他更关键/缺乏的方面。

我不同意讨论的另一个方面是与 React 的不断比较。 我理解它的相关性,但我不希望 Flutter 成为没有 JS 桥并将组件名称更改为小部件的 React 的副本。 如果都一样,那为什么要改变呢? 这并不意味着 Flutter 应该尽量远离 React。 Flutter 应该有自己的身份。 我更喜欢提供解决方案的 Flutter 文化是主动的,而不是被动的。 我们应该仅将 React 用作​​对比点,而不是作为指南。

就我而言,如果任何开发人员因为不支持 DSX/JSX 而选择不使用 Flutter 进行开发,那么那个人根本不想加入 Flutter。

我不同意讨论的另一个方面是与 React 的不断比较。 我理解它的相关性,但我不希望 Flutter 成为没有 JS 桥并将组件名称更改为小部件的 React 的副本。 如果都一样,那为什么要改变呢?

因为 React 有 Flutter 可以填补的空白,然后你创建了比 React 更好的东西,因为它修复了 React 在 Dart 性能和 GPU 加速图形方面的缺点,同时保留了 React 的最佳部分以及它的熟悉度。

就我而言,如果任何开发人员因为不支持 DSX/JSX 而选择不使用 Flutter 进行开发,那么那个人根本不想加入 Flutter。

没关系,最终的结果是,如果使用跨平台工具的移动开发者不加入 Flutter,Flutter 在市场上就会失败。 所以 Flutter 需要吸引 React Native 开发者来生存。

谈到进化,它不是“适者生存”,而是“适应性最强的生存”。 适应或你灭亡。

@cbazza

没关系,最终的结果是,如果使用跨平台工具的移动开发者不加入 Flutter,Flutter 在市场上就会失败。

什么? 为什么需要? Flutter 可以在它处于 beta 阶段时形成自己的利基市场(因为它已经非常成功地做到了),然后有机地发展,而无需吸引具有表面相似特征的飞蛾。 还有你说的“失败”是什么意思? Flutter 不需要流行就可以成功。

@naiveaiguy
看,我知道你对 cbazza 的回复投了反对票。
但是,在你否决我的回复之前,你能花 15 秒来看看这个吗?

在您考虑 DSX 之前。
看看下面,它只是一个 JSX。

建立导航栏和正文后,您可以从导航条码中导入导航条码。

import XXXXX, { Component } from 'XXXXX';
import { Text, View } from 'XXXXX-native';
import navbar from "your code1"
import body from "your code2"

class SomethingFast extends Component {
  render() {
    return (
      <View>
        <navbar
            style={{width: 360, height:90}}
         />
        <Image
          source={{uri: 'https://google.com/dsx.jpg/'}}
          style={{width: 320, height:180}}
        />
        <body/>
        <Text>
          Look at <strong i="11">@escamoteur</strong> s code from above.
           Can you export part of UI code to another place,
           separate it into different modules, and read everything in few seconds or less?
        </Text>
      </View>
    );
  }
}
       I think cbazza is right.
       If flutter uses DSX or whatever that is JSX,
       it is a perfect UI framework.

       So, could we have something
       similar or better in the future?
       Or do you really think that the
       current is fine?

也许有人讨厌 JSX,因为它来自 Facebook,但实际上,它来自日本一家小型游戏公司。

使用 React Native 和 Flutter 完成应用程序后,我觉得在当前状态下,JSX 比纯嵌套的 Dart 类更容易阅读和调整。
然而,如前所述,Facebook 有理由使用 JSX,因为 JavaScript 是如何编写的(例如,没有命名的构造函数参数),而 Dart 并非如此。 此外,添加的 Dart 类型安全性确实不错!
因此,如果 Flutter 最终坚持使用纯 Dart 语法,我希望看到语法荧光笔和自动格式化程序的改进。 新的结束标签注释已经是一个很大的改进,但还不足以达到 JSX 的生产力。

@JonathanSum您正在解释可重用组件的想法。 你不需要 JSX 来做可重用的组件。 我认为通过引用 Dart 的语法可以得到更好的东西,但 DSX 根本不是一个好的方法。

@hartmannj我们一直在寻找有助于提高生产力的 Dart 语法、荧光笔和格式化程序的改进。 对于您或其他人可能想到的有关此类改进的任何具体想法或建议,我很想了解更多信息。

恕我直言,无需使用new/const已经有很大帮助。 我在飞镖格式格式化树的方式上遇到了真正的困难。 与以下相比,它没有足够强调树结构恕我直言:

    return Scaffold(
      appBar: AppBar(title: Text("WeatherDemo")),
      resizeToAvoidBottomPadding: false,
      body: 
        Column(children: <Widget>
        [
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: 
            TextField(
                    key: AppKeys.textField,
                    autocorrect: false,
                    controller: _controller,
                    decoration: InputDecoration(hintText: "Filter cities",),
                    style:  TextStyle(fontSize: 20.0,),
                    onChanged: ModelProvider.of(context).textChangedCommand,
                    ),
          ),

https://reactjs.org/docs/introducing-jsx.html

React 不需要使用 JSX,但大多数人发现在 JavaScript 代码中使用 UI 时,它作为一种视觉辅助很有帮助。 它还允许 React 显示更多有用的错误和警告消息。

当这么多开发者渴望使用 JSX 来构建 UI 时,就意味着需要这种方式,他们不应该被忽视。

@woodstream那种渴望使用 JSX 的人已经是 React fanboys 的粉丝了。 他们已经在使用 React Native。 Flutter 迎合了一种非常不同类型的开发人员。

编辑:我承认我在这里对 fanboy 的使用是错误的。

@naiveaiguy@Hixie

那种渴望使用 JSX 的人已经是 React 的忠实拥趸。 他们已经在使用 React Native。 Flutter 迎合了一种非常不同类型的开发人员。

你错了,你的名字叫分裂评论('React fanboys'和'不同类型的开发者')是不受欢迎的。 JSX/DSX 具有技术优势,其他人更喜欢它。 这个帖子是为了讨论,如果你不喜欢它,请退订。 也不要再对我的每一条评论都投反对票了,这对你来说并不是个好兆头。

我只是建议提供两种方式供开发者选择他们喜欢的方式,并且有人喜欢在不同的意见面前竖起大拇指? 技术应该是开放和包容的,而不是在封闭的社区中玩耍。

@anders-sandholm 我同意@escamoteur关于增强小部件树可见性的必要性。 我会做他的例子,如下所示:

return
      Scaffold(
          appBar: AppBar(title: Text("WeatherDemo")),
          resizeToAvoidBottomPadding: false,
          body:
        Column(children: <Widget> [
          Padding(
              padding: const EdgeInsets.all(16.0),
              child:
            TextField(
                key: AppKeys.textField,
                autocorrect: false,
                controller: _controller,
                decoration: InputDecoration(hintText: "Filter cities",),
                style:  TextStyle(fontSize: 20.0,),
                onChanged: ModelProvider.of(context).textChangedCommand,
            ),
          ),
        ])
      );

此外,我可以想象用不同的颜色、字体样式或粗细来突出显示 Widget 类名称,这样它就会更加容易识别。

@cbazza

点名? 我并没有暗示这些人是消极的,只是他们不同。 我确实喜欢这个帖子,但指责我恶意争论有点讽刺。

“fanboy”这个词通常被认为是一个贬义词,在这种情况下也是如此。 我建议在这里的讨论中避免使用这样的词。

请大家保持文明和建设性。 我们在这里讨论风格,这是一个非常主观的东西,所以无论每个人多么喜欢自己的喜好,它都不太可能天生就优于其他人。 请列出您在现有和建议的语法中看到的优点和缺点,但请记住,并非每个人都以相同的方式看待它,这很好。

@hartmannj

只是一些小的澄清...

然而,如前所述,Facebook 有理由使用 JSX,因为 JavaScript 是如何编写的(例如,没有命名的构造函数参数),而 Dart 并非如此。

实际上从 ES2015/ES6 开始,JS 就有了命名参数; 你可以只使用“解构”:)
这是一个例子:

// function declaration
function findUsersByRole ({
  role,
  withContactInfo, 
  includeInactive
}) {
  if (role === 'admin' && withContactInfo) {
  ...
  }
...
}


// usage
findUsersByRole({
  role: 'admin', 
  withContactInfo: true, 
  includeInactive: true
})

https://medium.freecodecamp.org/elegant-patterns-in-modern-javascript-roro-be01e7669cbd

此外,添加的 Dart 类型安全性确实不错!

您可以使用 DSX 获得相同的类型安全性,这确实很好。

由于这是先前报道的https://github.com/flutter/flutter/issues/11609的副本,因此我将关闭这个以支持那个。

我真的不明白人们如何投票反对这一点——这对于互联网时代的声明性代码的编写方式来说是如此的第二天性..

<like><this /></like>

请足够灵活,让 Flutter 有机会飞翔!

遗憾的是,这看起来毫无希望,过去甚至现在每项技术都使用标记来创建 UI,所有开发人员的经验现在都被颤动浪费了。

我们不需要像 react native 或 html 那样做,只需使用简单的xml

还有也许...嵌入飞镖的xml! ;P

2018 年 8 月 28 日星期二 21:29,Touseef [email protected]写道:

我们不需要像 react native 或 html 那样做,只需使用简单的xml


您收到此消息是因为您发表了评论。
直接回复此邮件,在 GitHub 上查看
https://github.com/flutter/flutter/issues/15922#issuecomment-416550338
或使线程静音
https://github.com/notifications/unsubscribe-auth/AC8aNdVb_NV8c8JH4t36OS1OOvX6kY58ks5uVSmjgaJpZM4S6HPa
.

--
托尼·波里内利

对我来说,类似 JSX 的功能是未来,它将成为 React、Vue 和 Flutter 等声明性框架的标准构造。

如果我们只有 2 个用于 UI 和逻辑的单独文件,我们不需要在 dart 中嵌入 xml,那么我们可以轻松地遵循 mvvm、mvc 或任何其他所需的模式。

我已经在另一个线程中说过,但是:

如果你真的想要 JSX,一个好的入门者是使用代码生成。 使用.html.xml文件并从中生成小部件。

显然,这不是一个成熟的 JSX,但它是一个开始。 足以看到社区对此有何反应。
如果该语法获得关注,Flutter 团队可能会重新考虑该主题。

否则,我认为这只是浪费时间。 从这里我们可以清楚地看到,这是一个备受争议的话题。

如果颤振引入和 xml / jsx / 称之为你想要的创建 UI 的方式,我会立即开始将它用于生产级应用程序!

我同意@leossmith是生产级应用程序的唯一障碍。

我个人更愿意_不_添加 JSX 或外部标记语言。 我更喜欢将所有内容都保存在一种经过类型检查的语言中。 我觉得更好的方法是继续改进 Dart 语言,以编写深度嵌套的声明性 UI 树。 他们已经在这方面添加了一些不错的功能:

  • newconst关键字设为可选会有所帮助。
  • IDE 中的虚拟结束标签
  • dartfmt 也有帮助

我更喜欢用一种经过类型检查的语言来保存所有内容

这正是 DSX/JSX 所做的,语言是 DSX 的 Dart,JSX 的 Javascript !!!

我觉得更好的方法是继续改进 Dart 语言,以编写深度嵌套的声明性 UI 树。

DSX 是对 Dart 语言的改进,以更好地支持深度嵌套的声明性树。 就像 JSX 用于 Javascript 一样。

https://facebook.github.io/jsx/

本规范的目的是为定义具有属性的树结构定义一种简洁且熟悉的语法。

@cbazza你提出了一个很好的观点。 JSX 是对 JavaScript 的公正和改进。

所以首先让我们清楚地分开两件事:

  1. 用于定义 UI 的外部 DSL。 我100%反对这一点。 我一直相信这会带来比它解决的问题更多的问题。 我写了一篇博客文章来论证这一点。 它获得了 58K 的浏览量,令人惊讶的是,几乎没有异议:我 80% 的编码都是这样做的(或者为什么模板已经死了)
  2. 语言改进。 为了更容易构建和可视化深度嵌套的 UI 树结构。 在这一点上,我们都同意还有改进的余地。

但我们在方法上略有不同。 JSX 对 React 更有意义有两个原因:

  1. 数据结构:在 Web 上,JSX 完全匹配正在生成的东西(HTML DOM 节点)。 在 Flutter 中,我们正在生成 Widget 实例。
  2. 熟悉度:人们习惯于查看 html 代码。 但是 DSX 提案与 JSX/XML 的偏差刚好足以使这一点失效。

下面是(我相信)使 XML 能够很好地(并且可读)构建 UI 树的两件事。 问题是,是否可以在不将 XML 引入语言的情况下实现这些:

  1. XML 有结束标签。 无论是否使用 xml-ish 语法,这都是可能的。 Visual basic 在 90 年代就有它(想想 End If)。 其他语言也有。 IDE 确实提供了“虚拟结束标签”,但这有点粗略。 我更喜欢语言支持。
  2. XML 对子项有特殊处理。 属性与子项不同。 但我认为这是一把双刃剑。 在某些情况下,Dart 在这方面实际上比 XML 更清晰、更具表现力。 例如,具有不同子内容模型的容器小部件:
MyWidgetA(children: [ w1, w2 ])
MyWidgetB(child: w1)
MyWidgetC(top: w1, bottom: w2)

结束标签问题的戴夫提案

ButtonsView(
        onDeal: onDeal,
        onHit: onHit,
        onStay: onStay,
)ButtonsView

这将很容易被人类阅读。 解析器只需将)ButtonsView替换为) 。 此外,IDE 可以为该方案提供更好的检查和帮助。 每当打开和关闭括号不在同一条线上时,我都会要求它。

嵌套儿童问题的戴夫提案

某些语言(如 kotlin)允许对 lambda 类型的 args 进行特殊处理。 它们允许您将 lambda 参数放在括号之外。 请参阅将 lambda 传递给最后一个参数

我为 Dart 提出了类似的建议,但作为 List 类型的 arg,而不是 lambdas。 我建议使用特殊语法来传递名为“children”的列表类型 arg:

```
//而不是这个:
Foo(a:1,b:10,c:44,儿童:[...])

//我们这样做:
富(a:1,b:10,c:44)[

]

对于带有单个子级或 2 个子级(如顶部和底部)的构造函数/函数,保持不变,没有变化。

我更喜欢用一种经过类型检查的语言来保存所有内容

这正是 DSX/JSX 所做的,语言是 DSX 的 Dart,JSX 的 Javascript !!!

我觉得更好的方法是继续改进 Dart 语言,以编写深度嵌套的声明性 UI 树。

DSX 是对 Dart 语言的改进,以更好地支持深度嵌套的声明性树。 就像 JSX 用于 Javascript 一样。

https://facebook.github.io/jsx/

本规范的目的是为定义具有属性的树结构定义一种简洁且熟悉的语法。

@StokeMasterJack - 您对结束标签问题的提议听起来与我前段时间的提议相同。
想法:自动生成的结束标签

我认为颤振需要这样的东西。 大多数时候,我都在努力在深巢中插入新的小部件。 我会使用类似 JSX 的语法来获取结束标记符号。

我不想写结束标签。 这在 JSX/html/xml 中很痛苦。 特别是当我想重构时。
我认为虚拟结束标签非常整洁。 这似乎是两个世界之间的一个很好的妥协。

如果我们真的需要在这里进行一些改进,我认为我们可以继续在 IDE 方面进行探索。 例如,vscode 提供了以下面板:

screen shot 2018-10-11 at 01 31 33

(很确定 Android Studio 也有)

我们也可以添加嵌套的构造函数,而不是停留在专注的方法上。
因此,当悬停特定类时,我们将获得以下 UI:

lib > main.dart > Foo > build > Container > Center > Text 

如果它是关于将视觉小部件与其他类型的内容分开,IDE 也可以再次这样做。

我们可以为小部件设置不同的语法高亮。 我们可以为小部件子类指定特定的颜色,而不是用于类的常用颜色


如果是关于可编辑性,那么 Flutter 已经提供了你需要的所有工具。

有很多重构选项,包括:

  • 包装成新的小部件
  • 删除小部件
  • 与孩子交换小部件
  • 与父级交换小部件

考虑到这些,您不必再处理括号了。


老实说,几个月来,我每天都花几个小时在 Flutter 上玩。 而且我在编写嵌套小部件时没有感到任何缺乏可读性或任何不适。
相比之下,我使用 React 的次数也差不多,而且有些东西让我感到沮丧。

@rrousselGit - 您拥有的那些重构选项听起来很有用。 我在 Android Studio 3.2 上看不到它们。
我认为 Android Studio 会为 Flutter 开发提供最好的功能。

@Rockvole

这是 Android Studio 的截图:

image

作为快速修复Option+Enter (macOS) 激活。
我一直在使用这些,非常有帮助。

关于主题:Flutter 团队似乎正在探索“UI 即代码”的选项,我们迟早会在这方面得到更多改进。 尽管@StokeMasterJack的想法听起来很有趣。

@Rockvole伟大的思想都一样!

@StokeMasterJack

不错的回复!!!

JSX 对 React 更有意义有两个原因:

  1. 数据结构:在 Web 上,JSX 完全匹配正在生成的东西(HTML DOM 节点)。 在 Flutter 中,我们正在生成 Widget 实例。

JSX 的强大之处不在于生成 HTML/DOM 节点,而在于管理组件层次结构; React Native 没有 HTML/DOM 节点,对吧?

  1. 熟悉度:人们习惯于查看 html 代码。 但是 DSX 提案与 JSX/XML 的偏差刚好足以使这一点失效。

就像上面一样,它不是关于 HTML 代码,而是关于一种语法,它与宿主语言的命令式结构明显分开,并为构建树层次结构尖叫声明性标记

我不喜欢您的提议或 Kotlin 的提议,因为它看起来像是为了避免进行正确设计而进行的黑客攻击。 现在我必须查看代码并尝试弄清楚它的作用,而不是设计一个看起来与众不同的 DSL; 语法看起来模棱两可。 将命令式和声明式构造分开是有好处的; 例如,第 3 方工具可以轻松地在代码中定位 XML 标记。

@Rockvole

我会使用类似 JSX 的语法来获取结束标记符号

很高兴知道 ;)

@rrousselGit

我不想写结束标签。

你不必; 例如,WebStorm 会自动生成结束标签,它甚至会在您编辑另一个标签时重命名打开或结束标签。 其他人应该遵循的非常棒的编辑器功能(看着你的“VS Code”)。

老实说,几个月来,我每天都花几个小时在 Flutter 上玩。 而且我在编写嵌套小部件时没有感到任何缺乏可读性或任何不适

我希望你能明白你的经历并不能反映其他人的经历。 使用工具,编写不像阅读代码那么痛苦。 去github看别人的代码,你会发现读起来很痛苦,代码太冗长,嵌套结构太长。 看起来在 async/await 出现更好的方法之前使用了 Promise-chains。 此外,感觉声明式技术不如命令式技术重要; 我的意思是为什么没有声明性矢量图形结构? 相反,例如,我必须使用对 Skia 的命令式调用来绘制矢量图形。

你不必; WebStorm 例如自动生成

Vscode 也是这样做的。 但它仍然不完美。 尤其是在移动事物时的重构步骤。
我认为虚拟标签在这里提供了更流畅的体验。

我希望你能明白你的经历并不反映其他人的经历

当然 ! 我只是想指出,这可能更多是对工具的缺乏经验,然后是实际缺乏😄

去github阅读别人的代码,你会发现阅读是一种痛苦,[...]

我不太明白您的论点与该主题有何关系。
您列出的问题来自不良做法,而不是语法错误。 如果人们想要制作一个 500 长的小部件树,这不是 Flutter 的错。

@pulyaevskiy - 感谢有用的提示,在 Linux 上,快速修复是 Alt-Enter。 不是一个很容易发现的功能,我搜索了顶部菜单选项,但除了神奇的按键外,它似乎无处可寻:)

我认为虚拟标签在这里提供了更流畅的体验。

例如,这些虚拟标签是否显示在 github 的源文件中?

我不太明白您的论点与该主题有何关系。

基本上,该语言可以提供结构来使事情变得不那么冗长,正如我在 promise 与 async/await 示例中提到的那样。 在 Flutter 中,构造函数非常庞大,而且很多时候它们需要很多参数; 例如,使用 DSX,您可以使用扩展运算符将 10 行构造函数压缩为 1 行构造函数,因此您仍然可以看到完整的树层次结构,并且周围的噪音更少。 这使得阅读代码更容易,并允许将样式与树结构清晰分离。 我并不是说这不能通过重构你的 Dart 代码来完成,但它可以在不费力气的情况下完成或重新构建周围的东西。 你不需要适应语言的限制,语言适合你。

您列出的问题来自不良做法,而不是语法错误。

在 async/await 之前,最佳实践是到处使用 Promise 而不是疯狂的事件回调。 使用 Promise 会导致 async/await 解决的可读性问题。 它与语法糖基本相同,但在阅读别人的代码时 async/await 更清晰。

这是一个可怕的例子@woodstream

更新:只是为了说明我的观点,而不仅仅是在没有任何论据的情况下抨击的话。 DSX 等价物也一样长……这与行数或 HTML 无关。

class MusicImage extends StatelessWidget {

  TextStyle titleTextStyle = TextStyle(
    fontWeight: FontWeight.w800,
    letterSpacing: 0.5,
    fontSize: 20.0
  );

  Container titleText = (
    <Container height={116.0} padding={EdgeInsets.all(10.0)}>
      <Text style={titleTextStyle}>title</Text>
    </Container>
  );

  TextStyle authorTextStyle = TextStyle(
    fontWeight: FontWeight.w800,
    letterSpacing: 0.5,
    fontSize: 10.0,
  );

  Container music = (
    <Container
      height={40.0}
      decoration={BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.all(Radius.circular(8.0))
      )}
      padding={EdgeInsets.fromLTRB(0.0, 5.0, 5.0, 0.0)}
      margin={EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 0.0)}
    >
      <Stack>
        <Row>
          <Container
            height={30.0}
            width={30.0}
            decoration={BoxDecoration(
              borderRadius: BorderRadius.all(Radius.circular(8.0))
            )}
            margin={EdgeInsets.fromLTRB(5.0, 0.0, 5.0, 0.0)}
          >
            {Image.asset('images/bg2.jpg')}
          </Container>
          <Column>
            <Text>music</Text>
            <Text style={authorTextStyle}>author</Text>
          </Column>
        </Row> 
        <Align alignment={FractionalOffset.centerRight}>
          <Icon icon={Icons.play_arrow} />
        </Align>
      </Stack>
    </Container>
  )

  <strong i="9">@override</strong>
  Widget build(BuildContext context) {
    return (
      <Container
        height={168.0}
        margin={EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 8.0)}
        decoration={BoxDecoration(
          borderRadius: BorderRadius.all(Radius.circular(8.0)),
          image: DecorationImage(
            image: new AssetImage('images/bg.jpg'),
            fit: BoxFit.cover,
          ),
        )}
      >
        {titleText}
        {music}
      </Container>
    );
  }
}

作为一个 React 开发者,我认为这个社区需要做的是自己提供这个特性,当开发者开始适应它并实际使用它时; 然后,主要贡献者也将被迫对其进行本地调整。 我是一名 React 开发人员,在处理如何用 Flutter 编写 UI 时遇到了很多问题,我很想转向 Flutter,但语法没有帮助,我什至会研究如何实现类似 JSX 的语法我自己,正如之前所说的“很高兴有这个选择”。

我认为人们反对这一点的主要原因之一是他们无法想象他们会使用它。 事实是,您真的不必这样做,就像人们使用(比较反应) React.createElement(Component, {}, null)而不是<Component />如果实现这一点,这将吸引人们首先使用 Flutter地方,这就是我们真正想要的。 一个致力于 Flutter 并相互支持的大型社区。 如果这不是您会使用的那种语法,那么好吧。 但是与当前的方法相比,tons 更喜欢类似 JSX 的表示法。

就我个人而言,我认为 SGML 及其衍生品简直丑陋。 如果我们正在做一个 DSL,为什么不使用类似 QML 的语法呢?

我还认为一些支持 DSX 的观点将 Javascript 作为一种语言的特性(Dart 作为一种语言没有)和 JSX 作为一种 DSL 的特性混为一谈。 例如,

基本上,该语言可以提供结构来使事情变得不那么冗长,正如我在 promise 与 async/await 示例中提到的那样。 在 Flutter 中,构造函数非常庞大,而且很多时候它们需要很多参数; 例如,使用 DSX,您可以使用扩展运算符将 10 行构造函数压缩为 1 行构造函数,因此您仍然可以看到完整的树层次结构,并且周围的噪音更少。

这不是 DSX 会神奇地授予的功能,而是 JSX 拥有的功能,因为 Javascript 拥有它。 Dart 作为一种语言可以获得扩展运算符(不太可能是 IMO),在这种情况下,您可以将它与构造函数和其他函数调用一起使用,而无需特殊的 DSL。 这也是一个很有效的特性,因为 Javascript 的对象、hashmaps 和数组本质上都是一样的,这绝对不是 Dart 的情况,而且几乎肯定永远不会改变。

我认为这是许多反对该提案的人所面临的问题,即使它没有被发声 - 它本质上是要求 Dart 像 Javascript 一样表现(或假装表现),虽然有一些优点,但事实是它们只是不同的语言,自 Dart 1 早期以来,它们的差异越来越大。

编辑:这并不是说 UI 的标记/建模 DSL 完全是一个坏主意。 老实说不是,但我认为它的灵感应该来自比 Javascript 更类似于 Dart/Flutter 的语言/框架(在键入范式以及其他语义细节方面 - 我不是在谈论普通语法)是。

Dart 作为一种语言可以获得传播运算符(不太可能是 IMO)

事实上,集合的传播已经指定并准备好实施,请参阅传播集合和整个“语言漏斗”以获取有关即将推出的 Dart 语言功能的更多信息。

@mraleph我在谈论专门用于函数/构造函数调用和对象的扩展运算符,而不仅仅是列表或映射-我认为这是不太可能的。 抱歉,如果不清楚!

(我隐约知道这个提议,但我最后一次检查它你不能像传播/破坏 Javascript Size { width: 10, height: 10 } Size(10, 10)或传播列表/map 将参数映射到普通函数调用中(不使用Function.apply ,这会牺牲类型安全))

@filluchaos

就我个人而言,我认为 SGML 及其衍生品简直丑陋。 如果我们正在做一个 DSL,为什么不使用类似 QML 的语法呢?

因为很多人,不像你,不认为它丑,而是更喜欢它。 您不必有太多远见,就能看到所有热情的 React 开发人员。

JSX/DSX 将标记引入宿主语言 Javascript/Dart,以增强宿主语言并在标记上启用所有编程语言结构。 非常简单而强大的东西。

这不是 DSX 会神奇地授予的功能,而是 JSX 拥有的功能,因为 Javascript 拥有它。

一点也不真实; DSX 可以自己实现传播,不需要 Dart 支持。 如果它这样做会很好,但不是必需的。 这就是从高级语言转译为 Dart 的美妙之处,高级语言不需要受 Dart 的约束。

我的原型在线 DSX 转译器可以很好地处理传播运算符,请查看:
https://spark-heroku-dsx.herokuapp.com/index.html

我认为这是许多反对该提案的人所面临的问题,即使它没有被发声 - 它本质上是要求 Dart 像 Javascript 一样表现(或假装表现),虽然有一些优点,但事实是它们只是不同的语言,自 Dart 1 早期以来,它们的差异越来越大。

停止思考当前的 Dart 是什么,并通过从所有其他语言中汲取最好的想法来专注于它可能是什么。

我认为它的灵感应该来自比 Javascript 更类似于 Dart/Flutter 的语言/框架(在打字范式以及其他语义细节方面 - 我不是在谈论简单的语法)。

Typescript 是有类型的并且支持 JSX。 最接近 Flutter 的 UI 框架是 React,猜猜 React 是因为 JSX 而起飞的。 请想出比 JSX/DSX 更好的东西,如果你这样做了,人们将不再要求 JSX/DSX,但我还没有看到任何我认为更好的东西,所以现在 JSX 是最先进的.

很高兴看到 Dart 语言的人们从 Python 等其他语言(列表和字典理解)中汲取了最好的想法。

@cbazza

因为很多人,不像你,不认为它丑,而是更喜欢它。

反之亦然。 为什么这是一种语法而不是其他任何语法,尤其是当它与语言并没有真正的密切关系时? (在 Android SDK 中,Java 和 XML 已经有多年的关系。JavaScript 和 HTML 也是如此,JSX 非常相似。提议的 DSX 将带来基于它的 SGML 语法,对其他语言有意义,但不一定适用于 _Dart_)。

JSX/DSX 将标记引入宿主语言 Javascript/Dart,以增强宿主语言并在标记上启用所有编程语言结构。 非常简单而强大的东西。

一点也不真实; DSX 可以自己实现传播,不需要 Dart 支持。 如果它这样做会很好,但不是必需的。 这就是从高级语言转译为 Dart 的美妙之处,高级语言不需要受 Dart 的约束。

将这两个陈述并列看是相当有趣的,因为它们只是为了证明我的观点。 JSX 很棒(对于 Javascript),特别是因为它的简单性——它只是对已经是 JS 语言结构的糖,它本身并没有真正实现任何特殊的语义。 您正确地赞扬了这种简单性,然后继续说 DSX 应该独立于目标语言自行实现语义,显然没有认识到 1)需要做多少工作,以及 2)它如何完全违背了成为简单但功能强大的 DSL。

我的原型在线 DSX 转译器可以很好地处理传播运算符,请查看:
https://spark-heroku-dsx.herokuapp.com/index.html

我以前见过你的转译器,虽然它的工作令人印象深刻,但它绝不会像 Javascript 作为一种语言(以及 JSX)默认情况下那样处理扩展运算符。 正如已经提到的,传播(并最终解构)集合与 Dart 并没有太大的不同,实际上正在实施中。 传播和解构任何对象(与 JS 不同,它与 Maps 非常不同)是,并且您的转译器似乎也无法处理该对象(实际上需要在 Maps 中放置参数,这是相当单一的和不可用的 Dart(例如,不能以一种体面的类型安全方式与之交互))。

停止思考当前的 Dart 是什么,并通过从所有其他语言中汲取最好的想法来专注于它可能是什么。

当然。 但是在 Dart 可以使用的语言中,我个人认为 JS 在列表中的排名不是很高——老实说,我认为试图太像 JS(为了互操作性)在早期削弱了 Dart。

当然,我会喜欢 UI DSL。 但是 DSL 应该是 _Dart_ 的惯用语,而不是仅仅因为受欢迎程度而从语义不同的语言中大量提升。

而且我还希望人们不要将 Javascript 的功能与 DSL 的 JSX 功能混为一谈,因为提到的一些好处实际上是伪装的语言级功能请求。 继续使用扩展运算符,如果 Dart 作为一种语言确实支持 JS 中的所有运算符,那么我看不出return <SomeWidget {...someArgs, arg: newValue } />;return SomeWidget(...someArgs, arg: newValue);更适合阅读或类似 QML 的return SomeWidget { ...someArgs, arg: newValue }; ,除非对 SGML 有某种依恋。

@filluchaos

为什么这是一种语法而不是其他任何语法,尤其是当它与语言并没有真正的密切关系时? (在 Android SDK 中,Java 和 XML 已经有多年的关系。JavaScript 和 HTML 也是如此,JSX 非常相似。提议的 DSX 将带来基于它的 SGML 语法对其他语言有意义,但不一定对 Dart 有意义)。

停止将您认为可以在一起(并建立关系)的事物配对,并专注于挑选最佳创意,无论它们来自哪里。 当不需要时,您是一种人为地隔离事物。

我选择 JSX 语法是因为它在 React 中很受欢迎,这也是 React 人所期望和想要的。 这张票就是这样,如果那不适合你,请不要使用它。

将这两个陈述并列看是相当有趣的,因为它们只是为了证明我的观点。 JSX 很棒(对于 Javascript),特别是因为它的简单性——它只是对已经是 JS 语言结构的糖,它本身并没有真正实现任何特殊的语义。 您正确地赞扬了这种简单性,然后继续说 DSX 应该独立于目标语言自行实现语义,显然没有认识到 1)需要做多少工作,以及 2)它如何完全违背了成为简单但功能强大的 DSL。

不管它是否实现了新的语义,都无关紧要。 简单来自它的用法。 如果用户/开发人员易于使用,他们就会使用它。 用户/开发人员不关心内部事物的复杂程度(或要做的工作量),他们只关心它使他们的生活变得多么简单并改进了他们的代码。

我以前见过你的转译器,虽然它的工作令人印象深刻,但它绝不会像 Javascript 作为一种语言(以及 JSX)默认情况下那样处理扩展运算符。

我在 DSX 上传播的目的只是传播属性,而不是传播的完整 JS 实现。 它就其本身而言工作得很好,并且根本没有类型安全问题。 当 Dart 编译 DSX 生成的内容时,会发生类型检查/正确性。

在早期使 Dart 瘫痪。

早期让 Dart 受挫的不是提供简单的 JS 互操作性,因此当前的 JS 库可以很容易地与 Dart 代码一起使用(反之亦然)。 这也是 Typescript 在 Dart 失败的地方成功的原因。

当然,我会喜欢 UI DSL。 但是 DSL 对于 Dart 来说应该是惯用的,而不是仅仅因为受欢迎程度而从语义不同的语言中大量提升。

人气决定一切。 最好的想法是最好的想法,因为它们变得流行是因为很多人都欣赏它的好处。

而且我还希望人们不要将 Javascript 的功能与 DSL 的 JSX 功能混为一谈,因为提到的一些好处实际上是伪装的语言级功能请求。

同样,这无关紧要。

Google(Dart/Flutter)人员真正需要的是通过源映射提供通用的转译支持,以便可以开发针对 Dart/Flutter 的任何高级语言,并且它可以在当前工具(IDE、调试器等)上正常工作. 公平竞争,你保证最好的想法会来自其他人的平台。

@cbazza

我选择 JSX 语法是因为它在 React 中很受欢迎,这也是 React 人所期望和想要的。 这张票就是这样,如果那不适合你,请不要使用它。

这似乎相当分裂,对我来说相当有资格。 为什么 Flutter 应该对特定的 React 语法有一流的支持? 为什么不是 Vue 组件文件或 Xamarin.Forms 语法? 为什么 Flutter 的(可能是官方的)UI DSL 必须基于使用不同语言的不同框架的一组特定人的期望和想要的? 如果你想要一个专门为 React/JS 开发人员提供的社区工具,那将是一回事。 但是要求框架本身包含它只是为了满足你们所有人的需求,这有点 IMO 了。

不管它是否实现了新的语义,都无关紧要。 简单来自它的用法。 如果用户/开发人员易于使用,他们就会使用它。 用户/开发人员不关心内部事物的复杂程度(或要做的工作量),他们只关心它使他们的生活变得多么简单并改进了他们的代码。

在我看来,这是一种奇怪的权利形式。 不,开发人员关心实现的复杂程度,因为它开始引起问题和功能漂移,因为抽象的复杂性往往会这样做。 想要做的不仅仅是使用 DSL(例如扩展它)的开发人员肯定会关心实现的复杂程度。 必须构建和维护它的开发人员也是值得考虑的人。

我在 DSX 上传播的目的只是传播属性,而不是传播的完整 JS 实现。 它就其本身而言工作得很好,并且根本没有类型安全问题。 当 Dart 编译 DSX 生成的内容时,会发生类型检查/正确性。

如果您根本不考虑它,它只会“没有类型安全问题”。 我所说的是,参数的 Maps 与 Dart 代码库的其余部分并不能以完全安全的方式 _usable_ 使用,大概您希望像在 JavaScript 中使用 props 等方式与这些参数进行交互 - 将它们从另一个传递下来小部件,从另一个模块导入它们,等等 - 而不仅仅是在一个地方声明它们,在这种情况下,普通的构造函数调用有什么意义?

为了说明我的意思,您可以在 JS 中执行此操作:

class MyCustomSize {
  constructor(length, width, height) {
    this.length = length;
    this.width = width;
    this.height = height;
    this.calculateVolume.bind(this);
  }

  calculateVolume() {
    return this.length * this.width * this.height;
  }
}

const Cuboid = ({ length, width, height }) => { // blah blah }

const literalSize = { 'length': 30, 'width': 20, 'height': 10 };
const size = new MyCustomSize(30, 20, 10);

size.length = 100; // Can interact with the object as normal, no compromises
console.log(size.getVolume()); // and even call methods
size.foo = 50 // If you're using TypeScript, you get a nice error
literalSize.height = 15 // can interact with the hashmap as though it were an object

const SomeComponent = () => (
  <div>
    <Cuboid {...literalSize} />{/* valid */}
    <Cuboid {...size} />{/* also valid even though size is an object */}
  </div>
)

但是使用 Dart 和需要参数哈希映射的转译器:

class MyCustomSize {
  int length, width, height;

  MyCustomSize(this.length, this.width, this.height);

  calculateVolume() {
    return length * width * height;
  }
}

class Cuboid extends StatelessWidget {
  final int length, width, height;

  Cuboid(this.length, this.width, this.height);

  <strong i="9">@override</strong>
  Widget build(BuildContext context) { // blah }
}

Map literalSize = { 'length': 30, 'width': 20, 'height': 10 };
Map invalidSize = { 'length': 300, 'width': 200, 'height': 100 };
final size = MyCustomSize(30, 20, 10);

literalSize.height = 15; // Invalid, you must use square bracket notation which is honestly ugly to do a lot of the time
invalidSize['foo'] = 50; // No indication of anything wrong here

class SomeWidget extends StatelessWidget {
  <strong i="10">@override</strong>
  Widget build(BuildContext context) {
    return (
      <Column>
        <Cuboid {...literalSize} />{/* Yes, works */}
        <Cuboid {...invalidSize} />{/* Sure the transpiled code errors as there is no parameter named foo. But this is now a completely opaque error. What if the `foo:50` key-value pair was added in some other section of your codebase? In a third party library even? How do you debug that*/}
        <Cuboid {...size} />{/* How do you plan on handling this as a plain transpilation step? */}
      </Column>
    )
  }
}

早期让 Dart 受挫的不是提供简单的 JS 互操作性,因此当前的 JS 库可以很容易地与 Dart 代码一起使用(反之亦然)。 这也是 Typescript 在 Dart 失败的地方成功的原因。

Dart 与 JS 的互操作从未如此复杂,除非(这是我一直强调的一点)你只是想仍然编写 Javascript并且不愿意学习其他任何东西。 Typescript 作为超集与其说JS 的可操作性,不如说它只是 JS,以至于故意有一个不健全的类型系统只是为了迎合 JS(以及没有运行时来实际执行其表达类型系统,这是一个该死的耻辱这么多年)。 但回到我的观点,我个人觉得 Dart 为 JS 做出了很多糟糕的设计决定,而 Dart 2 真的应该是该语言的第一次迭代。

人气决定一切。 最好的想法是最好的想法,因为它们变得流行是因为很多人都欣赏它的好处。

“最好的”,或者说好主意是好主意,因为它们有优点。 有时它们会变得流行,有时它们不会。 有时坏主意会流行,有时则不会。 坦率地说,流行度是优点的直接指标是荒谬的,而且我个人非常不希望这种态度蔓延到 Dart 社区,尽管它很小。

Google(Dart/Flutter)人员真正需要的是通过源映射提供通用的转译支持,以便可以开发针对 Dart/Flutter 的任何高级语言,并且它可以在当前工具(IDE、调试器等)上正常工作. 公平竞争,你保证最好的想法会来自其他人的平台。

...我认为不可能比你以前更有资格,但我们到了。 为什么全球每一种高级语言都必须针对这个 UI SDK? 该提案再次强烈地以“让 Dart/Flutter 成为我的语言/框架”的形式出现——你不妨直接站出来说你想用 Javascript 构建 Flutter 应用程序。 是的,你的肘部要多费油,我会全力以赴为这样的社区项目做出贡献,但坦率地说,如果你要求官方支持,期待一个积极的答案是荒谬的。

再次重申——我不介意 UI DSL,我真的很喜欢。 但是,如果我们要求团队将其烘焙,那么它应该是 Dart 惯用的 DSL。 因为是的,我们这里有几十个人实际上喜欢 Dart 作为一种语言。

另一个编辑:请求 DSL 是一回事,建议 JSX 作为可能的语法/语法灵感,并对其他建议持开放态度。 对DSX的坚持让我(我怀疑许多评论过的人)错了。

@filluchaos

你非常困惑,我还没有太多时间可以浪费。

我对 Dart/Flutter 团队的唯一要求就是我之前所说的:

What we really need from Google (Dart/Flutter) people is generic transpiling support via source maps so that any higher level language can be developed that targets Dart/Flutter and it would work just fine with the current tools (IDE, debugger, etc). Level the playing field and you guarantee the best ideas will come to the platform from others.

这提供了实现 DSX、Vue 组件文件、Xamarin.Forms、NativeScript、QML 等所需的一切,因此将使社区能够提出他们想要的任何东西,而没有人需要“拿走”我的 DSX。 不喜欢 DSX,你可以使用普通的 Dart 或轻松创建自己的东西。

我会说您正在寻找诸如https://github.com/dart-lang/build和 dartanalyzer 之类的东西。
你可能会错过一两件(比如将分析器插件作为 pub 依赖项的能力),但我很确定 Dart 团队可以提供帮助。

无论如何,我不认为对彼此持续苛刻会以任何方式帮助框架进步。
我们从中得到的最大收获是另一个永久关闭的问题,因为它“太热了”。

@filluchaos

关于您的“foo”示例,DSX传播是编译时的事情,因此 map 需要定义为const或者我可以想出任何其他我想要在编译时发生的事情(例如创建一个新的 DSX 关键字或注释,后跟 const 映射)。 它必须在编译时,而不是在运行时,因为 Dart 不支持在运行时动态插入构造函数参数。 不是问题,因为它解决了我想解决的问题,即在构造函数上传播属性。

@cbazza关键在于,让扩展运算符在 JS/JSX 中如此方便的部分原因是您不必施加诸如“您只能使用哈希图”或“您的所有参数必须在编译时知道”之类的限制。或“您无法与要传递给 Widget 的参数/道具进行交互,就像您可以与其他所有内容进行交互一样”(请注意,您没有建议任何事情来处理具有您的属性的事物的情况需要实际上是一个对象,而不是地图文字)-0 当它是一个简单的例子时,一切都很好,但是在任何中型项目中,这种事情都会变得非常令人沮丧_fast_。 我的意思是,在什么时候停止堆砌变通方法、妥协和注释,退后一步,想知道扩展是否真的适合现有的语言?

JSX 之所以如此成功(与大多数模板相比),是因为它不会强迫您以某种方式编程(或者更确切地说,不会强迫您编写与 Javascript 不同的代码)。 使用 _any_ JavaScript 几乎完全没有痛苦; 这就是我创建一个真正适合该语言的 DSL 的意思。 这与 Redux 类似。 JS 代码库中的 Redux 是一件很美的事情(如果使用得当); 另一方面,与使用 Streams/BLoC 模式相比,我看到的所有使用 Redux 的 Flutter 示例确实看起来很痛苦。 这并不是说没有什么东西可以与巨大的成功重叠:React 的Context和 Flutter 的InheritedWidget实现了一个共同的概念,可以很好地满足两者的优势。 我只是不相信 JSX 目前是其中之一-除非进行一些语言级别的更改,否则老实说,开发 DSX 会很痛苦_并且_除了用于微不足道的示例之外,使用它也很痛苦,而人们可能会写在一个懒惰的周末从头开始一个功能完整的 JSX 转换器,因为它映射到 JS 是多么简单。

另外我之前有点咄咄逼人,我道歉。

@filluchaos

我并不是要创建一个完全通用的传播运算符,它可以在任何地方和所有事物上工作,甚至计划用于未来 Dart 的扩展运算符也不像 JS 那样通用。 我希望在DSX的上下文中处理的内容很好。 例如,DSX 不需要传播对象。

传播集合
https://github.com/dart-lang/language/issues/47

我已经使用 JSX 开发了超大型项目,并且真的从来不需要在标签属性上使用扩展。 没有它,JSX 工作得很好。 我添加到 DSX 的原因是因为它解决了 Flutter 小部件的一个问题,即没有简单的解决方案,特别是如果一个小部件在构造函数上采用 20 个参数,你怎么能用少于 20 行的连续行来编写这个小部件树一个厄运金字塔。 DSX 传播的唯一功能是能够将其中一些行从树中取出并将其放置在其他地方。

@cbazaa我正在评估是使用 React Native 还是 Flutter。 倾向于 Flutter,因为一切都只是 Dart,以便编译器可以检查我的 UI 拼写错误。 另请参阅: https ://medium.com/flutter-io/out-of-depth-with-flutter-f683c29305a8

JSX 也会发现我的错别字吗? 我使用打字稿。

我讨厌 HTML / 单独的标记。 例如,在 Angular 中,如果我在 HTML 中输入错误的内容/变量,我只会在渲染页面后发现我的错误。

@sivabudh

JSX 也会发现我的错别字吗? 我使用打字稿。

是的,在使用 JS/ES6 时,一些 JSX 拼写错误在编译时被捕获(例如组件名称),但不是 prop 名称(将在运行时被捕获); 但是由于您使用的是 TypeScript,因此类型系统会在编译时捕获所有 JSX 拼写错误:
https://www.typescriptlang.org/docs/handbook/jsx.html

@cbazzadsx开源的吗?

@pushqrdx
还没有,我还没有发布它的源代码。

作为 React + TypeScript 和 Flutter 的消费者,我可以将自己作为测试人员。 干杯

我们会有 dsx 源吗? 这将是非常棒的!

我赞赏 cbazza 的努力,但我不会在 Flutter 中使用 DSX。 不过,很高兴测试它。

问题 #27141 跟踪向构建系统添加代码生成支持。 这将通过带有Builderhttps://github.com/dart-lang/build来完成。 理论上,当此功能准备就绪时,连接 dsx 编译器/转译器应该相当简单。

两期之后,我第一次遇到这么顽固的团队。

这里不是讨论 JSX,而是讨论嵌套地狱

就算不能给出 JSX 方案,也应该少嵌套,代码可读性更高

我认为 JSX 的优势是显而易见的,但 Flutter 团队却试图忽略它。

JSX 没有解决嵌套问题。 React 面临同样的问题

如果你不喜欢嵌套,你可能想看看hooks ,它是 React 钩子的一个端口,它本身就是解决嵌套地狱的尝试。

我认为我们应该找出为什么 JSX 会出现。 那是因为h/createElement函数写得不好,代码可读性差。 没想到flutter现在写的比h/createElement函数差10000倍,肉眼可见

JSX 的出现是因为 React 的核心是 Javascript 和 HTML 的混合。 带有 Javascript 插值/注入的 XML 语法自然地创建了 JSX。

Flutter 完全独立于 Javascript 和 HTML,因此它不能很好地转换为 JSX。 我同意 Flutter 项目通常是非常嵌套的,这可能是一个真正的痛苦,尤其是当dartfmt破坏这些重度嵌套的行时。 可怕。

我还要指出,当我刚接触 Flutter 时,我觉得它的结构非常糟糕,来自 React,但是当你通过最初的学习曲线时,Flutter 客观上更容易使用。 学习曲线并不是 Flutter 独有的,在学习新框架时很常见。 Flutter 尤其困难,因为它没有理由像许多人熟悉的 HTML 语法那样行事。

我认为有一些方法可以改善嵌套问题,而 JSX 不是答案。

一些想法:

  1. 开发一个内部风格指南,要求人们将大量的颤动树分解成更小的组件。

  2. 获取dartfmt以正式认识到 Flutter 与 Dart 包相比具有一组独特的格式化需求,并与 Flutter/Dart 团队合作提出合理的解决方案。 @优厚

  3. 使用像@rrousselGit@stateless包这样的代码生成,让开发人员更容易做第一件事

公平地说,嵌套问题主要出现在不想折射我们的代码时。

小部件被分成许多小块。
使用和滥用extract widget重构工具。

这既使代码更具可读性,减少冗余,甚至可能修复错误/增加性能。

虽然我在很大程度上同意,但 Flutter 小部件的级别如此之高,以至于我看到很多人在一个小部件中完成整个视图,因为......它实际上工作得非常好,你不必通过 4-5 传递道具小部件的级别。 你在这个过程中失去的是你得到这个可怕的嵌套代码, dartfmt粉碎成无法识别的东西。 所以我明白人们为什么这样做,我明白有一个解决方案,但我也明白为什么人们不使用这个解决方案。

JSX 的出现是因为 React 的核心是 Javascript 和 HTML 的混合。 带有 Javascript 插值/注入的 XML 语法自然地创建了 JSX。

你如何解释 React Native 使用 JSX 而它与 HTML 无关的事实?

你如何解释 React Native 使用 JSX 而它与 HTML 无关的事实?

因为它使用 React。 他们可能不想重新发明语法

因为它使用 React。 他们可能不想重新发明语法

所以 JSX 并不是像@lukepighetti所说的那样真正融合了 Javascript 和 HTML,而是XML-like syntax extension to ECMAScript without any defined semantics... who's purpose is to define a concise and familiar syntax for defining tree structures with attributes.
这一切都在规范中详细说明: https ://facebook.github.io/jsx/

据我了解,React 最初是作为带有jsx编译器的react + react-dom发布的,因此 HTML + JavaScript 混合很自然。 之后, react被用来驱动其他渲染器,如react-nativereact-vrreact-pdf等。所以我仍然坚持我原来的说法对 React 的历史和血统是合理和敏感的。 2019 年规范是 2019 年的规范,并未涉及 React 的历史。

我同意

但对我来说,还有一个更大的问题。 Vue 和 React 在这方面的工作方式类似。
React 有一个createElement和 Vue 有一个h函数。

我们从不在 React 和 Vue 中手动实例化组件。 这是处理它的框架。


Flutter 的行为不同。 我们直接操作 Widget 的实例。

因此,在 Flutter 世界中, <Foo />仅表示new Foo()

但在这种情况下,JSX 与 Widget 完全无关。 我们只是改变了在 dart 中实例化类的语法。

对我来说,这听起来像是我们失去了创建小部件的意义。

@lukepighetti
react-pdf不是另一个反应渲染器,你一定在想react-canvas
所以react != react-dom != react-nativereact包负责在JSX的帮助下管理组件层次结构,因此react不在乎它是否生成react-domreact-nativereact-canvas ,所以react并不是关于 HTML 的。

2019 年规范是 2019 年的规范,并未涉及 React 的历史。

没有像 JSX 的 2019 规范这样的东西。 JSX 只有一个版本,它是我提供的链接(https://facebook.github.io/jsx/)于 2014 年发布的原始版本。

@rrousselGit

我们只是改变了在 dart 中实例化类的语法。

对于带有 Flutter 的 DSX 而言,这正是转译器正在做的事情。

对我来说,这听起来像是我们失去了创建小部件的意义。

如果没有任何东西被删除,你怎么能失去一些东西,你只是获得另一种做某事的方式(有好处和缺点),现在你有选择的自由,选择最适合你的那个。

你好,我相信你可能对我的信息有误解。 react驱动其他反应渲染器,例如react-domreact-nativereact-pdfreact-vr等。Afaik、 reactreact-dom是同时发布的,所以在我看来, jsx的传承非常清楚。 我希望您不要深究我的信息,因为我们对 JSX 在 Flutter 上下文中的价值有不同的看法。 最好将其保持在主题上而不是分裂头发。

嗨 lukepighetti,你用 JSX 反应原生一到两个月了吗? 如果是这样,您必须了解为什么使用 JSX 和 react native 构建应用程序(或 react,我知道它们是不同的)框架样式简单且结构良好。
但是,如果你有一段时间没有使用过,你永远无法理解 JSX 为何如此有用和重要。

我仍然希望 Google 能够理解 JSX 的美妙之处,因为我们有很多人支持这一点。 谷歌团队有一天可能会考虑使用 DSX 或 JSX 作为 React 启发的框架,颤抖。

嗨 lukepighetti,你用 JSX 反应原生一到两个月了吗? 如果是这样,您必须了解为什么使用 JSX 和 React 本机(或 React,我知道它们是不同的)构建应用程序的框架样式简单且结构良好。

我不能代表 lukepighetti,但我已经专业地使用 React 工作了两年,现在正在做一些 Vue。 所以我非常精通 JSX。

同样,我也使用 Flutter 大约 2 年了。 起初,我还认为 Flutter 需要某种 JSX。
但是 Flutter 在那段时间进步了很多,我改变了主意。

  • JSX 很难手写。 它需要很多工具才能让它变得可以忍受,包括自动关闭标签、自动重命名标签和 emmet。 即便如此,它也远没有 Flutter 的语法那么简单。

例如,将Foo()重构为Foo(child: Bar())很容易。
但是将<Foo />重构为<Foo><Bar /></Foo>不是。

如果一个小部件同时使用childchildren怎么办? 我们得到:

<Foo
  child={<Bar />}
>
  <Bar />
</Foo>

?

在这种情况下,这意味着出于一致性目的, child应始终被视为命名参数,而不是使用children槽。

问题是,很少有小部件需要children 。 绝大多数是单个child或自定义命名参数的组合(如Scaffold )。

这意味着绝大多数使用 JSX 的小部件看起来像:

<Container
  child={<Bar />}
/>

那么哪个_更糟_:

Container(
  child: Bar(),
)

综上所述,我觉得 Flutter 还不错。 而且即使 JSX 可用,我怀疑它是否真的会改善事情。

就像我说的上行线程,我认为实际上是 JS/ECMAScript/一般 Web 功能(对象传播、解构、对象/哈希图的可互换性、所有 DOM* 节点具有高度相似的接口、HTML 在一般等)与什么是 JSX 功能。 前 IMO 使 JSX 编写起来很愉快。 没有它们,您只是在编写 XML,而我认识的大多数实际上可以选择的人都不喜欢编写 XML。

*值得注意的是,这首先是我对尝试将 Flutter 改造为 XML 的主要反对意见。 我认为试图否认 JSX/React 在 Web 中根深蒂固,并且 DOM 元素具有每个节点具有_attributes_ 和_children_ 的长期标准,我认为没有任何实际意义。 另一方面,Flutter 不会绑定开发人员为其他小部件children甚至child命名自定义小部件的插槽,我认为它应该开始这样做的原因为零。

我可以看到为什么另一个 JSX 线程被锁定了。 我不应该在 GitHub 评论中为我的技能/经验辩护,以解释为什么我认为 JSX 不会使 Flutter 受益。 我可以轻松地说“你没有足够的 Flutter 经验,无法对 Flutter 有任何意见。” 感觉不太好,是吗。 你们都喜欢你的键盘战士部落。

如果一个小部件同时使用childchildren怎么办? 我们得到:

为什么小部件需要同时具有childchildren ? 不是这个就是那个。
另一个话题,Flutter 的一些小部件使用children ,而其他的使用child ,没有人认为它复杂易混淆? children包含child ,所以没有不管你有多少child ,一个或多个,只要用children就可以完成工作。

@rrousselGit

JSX 很难手写。 它需要很多工具才能让它变得可以忍受,

不仅整个 React 世界不同意你的观点,整个 HTML 世界和 XML 世界也不同意。

Flutter 提供了许多重构选项,使操作括号更加容易

所以你说 Flutter 也“需要大量工具”,但由于你有偏见,你觉得有必要把另一面扔掉。 仅供参考:最好的做法是接受不止一种做事的方式,并且有些人会更喜欢另一种做事的方式。

他们真的做到了! 您可以从 IDE 进行代码审查。

这并不能解决团队使用的所有其他在线代码审查工具的问题。 这些工具操纵源代码,如果它不在源代码中,它就不存在。

JSX 不能很好地转换为 Flutter 模型。

那只是你的坏意见,任何人都可以看到 DSX 为 JSX 添加了与 Flutter 完美契合的增强功能。
https://spark-heroku-dsx.herokuapp.com/index.html

所以你说 Flutter '需要大量工具'

不,我说的是“更容易”而不是“可以忍受”。

我碰巧经常回答 StackOverflow/Slack,有时甚至是通过我的手机。
而且我在回答 html 相关问题时显然很糟糕——但 Flutter 很好。

最好的办法是接受不止一种做事的方式,而且有些人会更喜欢另一种做事的方式。

反之亦然。 你应该清楚地看到,社区并不是 100% 的 JSX 粉丝。 在这个问题和上一个问题上的反对票数量证明了这一点。

那只是你的坏意见,任何人都可以看到 DSX 为 JSX 添加了与 Flutter 完美契合的增强功能。

我不同意。 该语法包含许多在许多键盘布局上难以访问的复杂字符。
它也包含大量重复。


无论如何,我不明白你为什么总是如此咄咄逼人。 我们都在努力让 Flutter 变得更好。
严厉地让这个讨论结束是没有意义的。

如果 JSX 在 Flutter 中表现不佳,我可以接受不加入 JSX,但我们应该考虑嵌套地狱。

另一个小故事是飞镖语言的分号。 这真的很烦人。

另一个小故事是飞镖语言的分号。 这真的很烦人。

在 dart-lang/language 上有一个请求: https ://github.com/dart-lang/language/issues/69
去给它一个👍

这个长时间的讨论是关于能够使用这个:

<A property="a">
  <B/>
  <C/>
</A>

而不是这个:

A(property: a, children: [
   B(), 
   C()
])

即使有人同意前一种语法更好,但我个人不这样做,这会带来持续的维护成本、更高的复杂性和新的可能错误源,不仅在语言/框架中,而且在诸如 IDE 之类的周围工具中,调试器、linter 等。它还增加了构建时间。 它要求开发人员学习一种新的语法并专注于转译器的内部结构,以了解何时以及如何创建实例。 所有这一切几乎都是 React & co 的唯一目标。 开发商有宾至如归的感觉。

在开始使用新语言之前,我宁愿专注于改进 Dart,这远非理想,缺少模式匹配数据类ADT解构适当的选项等重要特性。其中一些 PR 已经开放 5+年。 这与添加装饰性和不必要的标记层来创建小部件相反,对架构、安全性和整体代码质量产生了巨大影响。

即使这被归为“社区驱动”,社区仍然可以花时间做一些有意义的事情。 但当然,每个人都可以利用他们的时间做他们想做的事。 请停止对 Flutter 团队施加这种不成比例的压力。

嘿,我舒茨。
有一个回复部分。

image

这就是我在这篇长文中一直在说的。 JSX 修复了“HTML 和 XML 的意大利面条问题”(不可读且复杂的 UI 代码)。 在我个人使用 Flutter 之后,它比 JSX 更复杂或更糟糕。

这些年来,我一直看到有人说 Flutter 无法捕捉到 React 的一些优点,例如,万物的真正思想是组件。

不确定我是否跟随。 在您突出显示的文本中,用户说他发现 JSX 更容易学习,因为他熟悉 HTML 并且具有相似的语法。 我看不出这如何证明 JSX 的存在是合理的,更不用说以任何方式模仿 Flutter。

我没有将回复添加到屏幕截图中,只是因为图像会占用太多空间。 他们似乎相当支持我发布的内容,因此也是多余的。 我发布了链接。

@JonathanSum是 Fl​​utter 比 JSX 更复杂,还是 Flutter 与 _React_ 不同,这会引起你的摩擦? 在某些情况下,它更冗长,是的,而且如果没有 IDE 中的虚拟结束标签,可读性可能会降低,但我不太确定使用构造函数比编写类似 XML 的 DSL 更复杂,我仍然不太确定为什么这么多人似乎认为说类似 XML 的 DSL 是灵丹妙药,可以让 Flutter 的使用更容易_理解_。 尤其是考虑到 Flutter 之前没有解决 React/JSX 旨在解决的问题的历史 - React 使 DOM 操作更容易和更清洁,这很好,但是这又与 Flutter 有什么关系呢?

这些年来,我一直看到有人说 Flutter 无法捕捉到 React 的一些优点,例如,万物的真正思想是组件。

在不触及 React 对 Flutter 所没有的一切都是组件的“真正”想法的概念的情况下,Flutter/Dart 的设计也有一些 React/JS 无法捕捉的优势。 对于大多数体面的 UI SDK/框架/库,您也可以这样说(反之亦然)。 令人难以置信的是,不同的项目实际上是不同的; 如果人们一开始并不期望它是[插入他们过去使用过的项目],那么参加一个项目的人可能会得到更好的服务。 🙂

这很可能是一个颠覆性的变化,但是参数自由的提议让我想到如果 Dart 有例如Crystal 的方法参数规范,那么构建方法会更加简洁。

当然,Crystal 的编译器会在与蛞蝓和乌龟的比赛中排在最后,所以就是这样😅

我现在同意不添加 JSX 并且不对 Flutter 施加额外的压力。

但就 dart 而言,它远不如 JS 或 TS 优雅。 我感到无助

比如微软 UI 技术的发展路线是 WinForm 到 WPF,而现在在 Flutter 中,放弃了 WPF 而改用 WinForm。针对开发者的抱怨,Flutter 团队努力实现了 WinForm 的可视化窗口和属性编辑器。

作为 Flutter 的新手,我必须说这应该在路线图中。 如果不是 jsx,一种更人性化的放置小部件的方式。

我现在可以看到一个反应类渲染函数和渲染类的图像和关联。

我可以看到一个 dart 文件和渲染的内容,我需要 5-6 分钟才能弄清楚它是如何工作的......

我可以在纯文本编辑器中在 5 分钟内制作一个半复杂的反应类,因为它很直观

我不能在颤抖中做到这一点。 如果没有自动完成,我就完成了开发人员的工作。 我不喜欢依赖扩展来开发某些东西-.-

然而。 飞镖开发人员如何处理这个“问题”将会很有趣。 在 dart 2 中,它们使其更具可读性。 我不知道他们将如何提高 dart 3 -4 -5 的可读性。 但我认为迟早需要重构组件构建功能。

编辑:
没关系,刚刚又尝试了 React Native,我讨厌 jsx,道具系统,一切都是动态的事实又是一个非常可怕的概念,我想这只是个人意见。 让颤动保持原样......

他们要求 DSX,不仅仅是因为他们喜欢 JSX。 他们想要 Flutter。

UI 声明应在代码中进行视觉分离,以获得更好的代码可读性和支持。 特别是在有很多初级/中级的大型团队中。 来自 Adob​​e Flex,我可以说阅读 Flutter 的 UI 声明会严重降低生产力。
如果不是 DSX(这将是很棒的 IMO),但至少在 IDE 级别上应该针对当前情况做一些事情。
所有以前的 UI 开发框架都有这个特性,我们也应该有它。

UI 声明应在代码中进行视觉分离,以获得更好的代码可读性和支持。

并更好地与其他工具(例如“gui builder”)集成。

来自 Adob​​e Flex,我可以说阅读 Flutter 的 UI 声明会严重降低生产力。

想象一下像 MXML 这样具有 Flutters 功能的 UI 声明! 我只能做梦!

既然我们已经有了 codegen 支持,那么将这样的东西融入产品的最佳方式是创建一个支持它并显示它非常受欢迎的包。

@Hixie是否有任何指向代码生成文档的指针?

既然我们已经有了 codegen 支持,那么将这样的东西融入产品的最佳方式是创建一个支持它并显示它非常受欢迎的包。

在我看来,codegen 仅适用于 .dart -> .dart,输入文件必须是有效的 .dart 文件。 这对于 .dsx 文件不是很有用,因为它是 dart 的超集。 我仍然需要支持使用源映射(如调试功能等)交叉编译成 .dart。

请给昨天发布的 SwiftUI 看看。 这似乎是 Flutter 的目标,而不是类似 React 的标记。

单单 Swift 的隐式成员表达式就太神奇了

我对 SwiftUI 语法感到困惑。 它肯定很精简,但有些方面看起来很神奇。

但从技术上讲,我们已经可以拥有一些相对相似的东西:

Column(mainAxisSize: MainAxisSize.min)([
  if (foo) Text('foo'),
  Text('bar'),
]);

这是有效的飞镖代码,其中Column _still_ 是一个类。

这是一个展示它的无状态小部件:

class Foo extends StatelessWidget {
  const Foo({Key key}) : this._(key: key);
  const Foo._({Key key, this.children}) : super(key: key);

  final List<Widget> children;

  <strong i="12">@override</strong>
  Widget build(BuildContext context) {
    return Column(children: children);
  }

  Foo call(List<Widget> children) {
    return Foo._(key: key, children: children);
  }
}

它是样板式的,但代码生成器可以提供帮助——尤其是对于即将到来的扩展成员。


这种方法的唯一问题是我们都丢失了 const 构造函数(因为它使用一个函数来指定子级)并实例化小部件类_twice_。

如果需要这种语法,最好不要使用call方法,而是应该使用构造函数柯里化来实现。

@rrousselGit我很好奇 SwiftUI 的哪些方面对你来说看起来很神奇 - 对我来说,这似乎是 Swift 语法的非常简单的扩展。

在他们代码示例中:

  • Content是可变的? 这是否意味着他们有一个内置的 Mobx / Vue 商店?
  • 那是什么@State
  • 为什么body是一个变量? 那是吸气剂吗? 如果是这样,什么时候再次调用吸气剂?
  • body是接口的一部分,还是Content中的许多类似变量?
  • item in _exactly_ 是做什么的? 为什么in的正确操作数不是可迭代的,而是“结果”?
  • 当没有HStack时,为什么Image与标题/副标题左对齐?

我记不太清了,但我很确定我在拿起 Flutter 时没有这样的问题。

@rrousselGit这可能是因为您的背景,而不是因为 Flutter 语法或语义本质上是显而易见的(我遇到过很多被它难倒的人)。 你提出的观点似乎是一个奇怪的交叉点,过度分析了一个 14 行代码片段的错误,而实际上并不知道它是用什么语言编写的。

  • 但它并不是真的可变(在 Dart 或 JS 意义上)? 这是一个结构。 此外,MobX/Vue 风格的商店(即对非常有限的语言支持进行纸面化)并不是处理可变性的唯一方法

  • @State是一个属性,在某些语言(例如 Dart)中也称为注解,在 Swift 代码中也称为非常常见的东西。 如果您的意思是它的作用,即使不查看文档,它也很可能将属性标记为会随时间变化的状态。

  • body是一个计算属性,这对 Swift 开发人员来说是显而易见的。 至于何时重新计算, Widget build(BuildContext context)是否也固有地告诉您何时再次调用它?

  • Content (对于 Swift 开发人员来说很清楚)扩展/实现View ,这是您寻找问题答案的地方(它实际上有一个非常好的 API 参考页面)。

  • 这几乎是“为什么这种语言中的关键字与我使用的语言中的关键字不同”,而不是特别“神奇”。 这里的in关键字与for...in构造不同——它表示闭包的主体即将开始。 { item in ... }是传递给List构造函数的函数块; ListViewitemBuilder ,如果你愿意的话。

  • 您是否合理地问为什么视图有自己的封装布局规则?

在 SwiftUI 上:

1-很高兴看到在视图中声明的状态,而不是作为侧面附件。

2-很好的单独方法来设置事物,而不必在构造函数上传递所有内容(方法使操作生效,而不仅仅是传入数据)。

3-很高兴看到声明性矢量图形与声明性的所有其他东西混合在一起(就像我过去建议的声明性 SVG 小部件一样)!!!
https://developer.apple.com/tutorials/swiftui/drawing-paths-and-shapes

4-非常简单的动画和过渡结构
https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions

5-Drag&Drop 设计工具与代码编辑器双向同步。

其他一切都有疣,但我宁愿专注于他们做得很好的事情。

这些“问题”的存在只是为了展示潜在的混淆点。 这些不是_实际问题_。

那可能是因为你的背景

可能。 我并不是说他们的方法不好或其他什么。 我是说这对我来说不像 Flutter 那样自然。
Flutter 小部件几乎不使用“花哨的语言功能”,并且几乎可以在任何语言上实现(尽管最近的 if/for for 集合改变了这一点)。
虽然他们对 SwiftUI 的展示广泛使用了 Swift 的特定功能。

至于何时重新计算, Widget build(BuildContext context) 是否也会固有地告诉您何时再次调用它?

我的观点是State与重新计算body的行为之间缺乏关系。
React 和 Flutter 在这方面非常明确:setState。
Vue/Mobx 是“神奇的”,使用相同的@State功能。

真的很好,但这是一个不同的模式。

您是否合理地问为什么视图有自己的封装布局规则?

不,它更像是“显式”与“隐式”。
似乎他们真的专注于“用尽可能少的代码做尽可能多的事情”,即使它隐藏了一些逻辑(在这种情况下, ltrrtl逻辑)

Flutter 会要求你使用Row

Flutter 使用并依赖大量“花哨的语言特性”(阅读:说话者不习惯和/或不同意的语言特性)。 就在我的脑海中,常量构造函数(以及 Dart 命名构造函数的一般风格)、运算符重载、作为隐式接口的类、 @covariant和 mixins 是会引起从混乱到直接标记为的反应的特性代码气味取决于开发人员的背景。 考虑一个小时,我可能会想出一个更长的清单。 这不是对 Flutter 的控诉,也不是对 SwiftUI 的控诉——我不明白为什么有人会认为用特定语言编写软件是一种美德,这样它就可以用任何语言以相同的方式编写——什么是如果我们应该假装它们之间不存在差异,那么不同语言的意义何在?

此外,我完全不同意setState@State中的任何一个都明确说明它与重建视图的行为的关系。 在这两种情况下,您都会被告知,如果您更改标记为状态的内容,框架将整理出要构建的内容。 在这两种情况下,开发人员仍然无法明确控制正在发生的事情或确切的时间。 会发现函数调用更熟悉,使用其他语言的人会发现装饰器更熟悉。 但是调用函数并不能使事情变得不神奇。

Flutter 会要求你使用Row

我认为您从未使用过ListTile ,它具有此处显示的相同行为但具有命名参数? 我们是否还应该问为什么Scaffold在您没有要求的情况下“神奇地”在您的应用栏左侧放置了一个菜单按钮?

不同之处在于,在当前状态下,Dart 与大多数主流语言非常相似。

这很重要。
问题“我需要学习 Dart,还是可以直接开始学习 Flutter?” 经常出现。
目前,答案是“只要学习 Flutter,一天就可以写出有效的飞镖”。
这不能保证永远保持这种状态,但我确实认为这是 Flutter 的优势之一。

剩下的讨论有点离题了。 如果您愿意,我们可以通过邮件继续该部分(我的 github 邮件有效)。

这个怎么没锁? 这已经严重恶化,与之前的锁定问题完全相同。

该线程已被自动锁定,因为它关闭后没有任何最近的活动。 如果您仍然遇到类似问题,请打开一个新错误,包括flutter doctor -v的输出和问题的最小重现。

此页面是否有帮助?
0 / 5 - 0 等级