【问题标题】:In Dart, if I listen to a click event with two listeners, how do I know which happens first?在 Dart 中,如果我用两个监听器监听一个点击事件,我怎么知道哪个先发生?
【发布时间】:2013-04-14 02:19:48
【问题描述】:

如果我编写以下 Dart 代码,我如何知道哪个点击处理程序首先发生?

main() {
  var button = new ButtonElement();
  var stream = button.onClick.asBroadcastStream();

  stream.listen(clickHandler1);
  stream.listen(clickHandler2);
}

假设我在其他代码中对前两个点击处理程序一无所知,但我注册了另一个。

  • 我可以知道流有两个侦听器吗?
  • 我可以暂停或取消所有其他订阅者吗?
  • 如果我在别处再次写入button.onClick.asBroadcastStream(),它是否指向与main 中使用的流相同的流?
  • 我可以在其中一个处理程序中说不要将事件传递给另一个广播侦听器吗?那是消费者吗?

【问题讨论】:

    标签: dart dart-html


    【解决方案1】:

    假设我在其他对第一个一无所知的代码中 两个点击处理程序,但我注册了另一个。

    我可以知道流有两个侦听器吗?

    不,你不能。您可以扩展流类或包装它并自己提供此功能,但感觉不是一个好的设计选择,因为我认为听众不应该了解其他听众。你到底想做什么?也许有比让听众了解彼此更好的方法。

    我可以暂停或取消所有其他订阅者吗?

    您只能cancel/pause/resume 您正在处理的订阅者。同样,您可能不应该接触其他侦听器,但我想您可以包装/扩展 Stream 类以具有这种行为。

    如果我在别处再次编写 button.onClick.asBroadcastStream(),它是否指向与 main 中使用的流相同的流?

    没有,至少在当前版本的 SDK 中没有。因此,不幸的是,您需要在某处存储对此广播流的引用并引用它,因为多次调用asBroadcastStream() 不会产生您可能期望的结果。 (注意:至少基于快速测试:http://d.pr/i/Ip0K 虽然documentation 似乎表示不同,但我还没有找到时间进行更多测试。

    我可以在其中一个处理程序中说不要将事件传递给另一个广播侦听器吗?

    嗯,在 HTML 领域中有 stopPropagation(),这意味着该事件不会传播到其他元素,但它可能不是您想要的。

    为了能够停止在其他侦听器中触发的事件,需要有一个调用侦听器的顺序。我相信顺序是那些听众的注册顺序。从设计的角度来看,我认为允许听众取消/暂停其他人不是一个好主意。

    HTML 中的事件传播是有意义的,因为它是关于层次结构的,但在这里我们没有(即使在 HTML 中的事件的情况下,单个元素也可以有多个侦听器)。

    没有办法为听众分配权重或定义重要性顺序,因此没有办法停止事件也就不足为奇了。

    与其让听众相互了解并相互操纵,也许您应该尝试考虑另一种方法来解决您的问题(无论是什么)。

    那是消费者吗?

    StreamConsumer 只是一个类,如果您想允许其他流通过管道传输到您的类中,您可以实现它。

    【讨论】:

    • 嗯我可能是错的,这个代码:d.pr/i/Ip0K 但是首先打印false 然后true。所以他们指的是不同的对象。当我找到时间时,我可能会对此进行更详细的调查。代码库中也可能会发生变化,请记住,您在答案中链接的内容与例如SDK 的 Stream 实现:)
    • 您的代码创建了两个广播流。如果您改为在您创建的第一个广播流上调用 asBroadcastStream() ,您将得到相同的结果。这就是被问到的。如果它是广播流,则流实现返回此值。我提到了问题中使用的流。
    • 嗯。我再次阅读了这个问题,我仍然认为他指的是我在屏幕截图中的代码示例中显示的内容,但我不会为此争论,所以我让提问者决定他想要什么。
    • 我又看了一遍,问题是button.onClick 每次调用它都会返回一个新的Stream,所以你是对的。我假设你每次都得到相同的流。如果您获取返回的流并调用asBroadcastSteam(),您将获得相同的实例。没有理由在它上面调用asBroadcastStream(),因为它已经是一个广播流。 :)
    【解决方案2】:

    我可以知道流有两个侦听器吗?

    不,您有一个包装 DOM 事件处理的“流”。没有这样的功能。

    我可以暂停或取消所有其他订阅者吗?

    查看Event.stopPropagation()Event.stopImmediatePropagation(),可能还有Event.preventDefault()

    如果我在别处再次编写 button.onClick.asBroadcastStream(),它是否指向与 main 中使用的流相同的流?

    [更新] 不,current implementation 不会返回相同的 Stream,因为 onClick getter 每次调用时都会返回一个新流。但是,返回的流已经是广播流,因此您不应在其上调用 asBroadcastStream()。如果你这样做了,你将获得对同一个对象的引用。

    Stream<T> asBroadcastStream() => this;
    

    我可以在其中一个处理程序中说不要将事件传递给另一个广播侦听器吗?那是消费者吗?

    再看看Event.stopPropagation()Event.stopImmediatePropagation(),可能还有Event.preventDefault()

    【讨论】:

    • Event.stopPropagation() 不会阻止调用其他侦听器(d.pr/i/4ZFx -- 打印两次)。它只是停止传播,由于层次结构,这也恰好是纯粹的 DOM 事物。请记住,流有多种用途,而不仅仅是 DOM。 :)
    • 你是对的,这就是即时版本的用途,但你只会停止随后的回调并且不能保证顺序......当然流用于很多事情,但问题是关于 DOM。
    • 我还应该补充一点,您不必在 DOM 处理程序上调用 asBroadcastStream(),因为它已经是一个广播流。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    相关资源
    最近更新 更多