// 同一托管对象系统中的事件阶段:祖先 capture → 目标 onEvent → 目标监听器 → 祖先 bubble。 // EventLog 用一个递增序列记录实际次序;改变监听器/传播标记可对比跳过与停止的语义。 // 保存各阶段序号与最近 phase;count 是共享状态,其他字段直接写在本模型中。 class EventLog { count: Object captureStep: Number methodStep: Number targetStep: Number bubbleStep: Number phase: String // 祖先捕获阶段先递增序列,再保存 captureStep 和 Event.phase。 function capture(self: EventLog, event: Event): Unit { self.count.increment() self.captureStep = self.count.value self.phase = event.phase } // 目标监听器的执行点;它排在目标类型 onEvent 方法之后。 function target(self: EventLog, event: Event): Unit { self.count.increment() self.targetStep = self.count.value self.phase = event.phase } // 祖先冒泡阶段记录最后序号,未被 stopPropagation 时才到达。 function bubble(self: EventLog, event: Event): Unit { self.count.increment() self.bubbleStep = self.count.value self.phase = event.phase } } // 覆盖目标方法,比额外 on(click,...) 监听器更早处理目标阶段事件。 class EventButton: Button { model: EventLog // 把模型序列递增后写 methodStep,供断言与 capture/target/bubble 比较。 function onEvent(self: EventButton, event: Event): Unit { self.model.count.increment() self.model.methodStep = self.model.count.value self.model.phase = event.phase } } model = EventLog(ui.state(0), 0, 0, 0, 0, "等待点击") button = EventButton("捕获 → 对象方法 → 监听器 → 冒泡", model) root = Column(24, 16, TextBlock("同一对象系统中的事件分派", 2), button, ui.textOf(model.count, "value"), ui.textOf(model, "phase")) // capture 选项显式选择捕获;不带选项的祖先监听器默认在冒泡阶段执行。 // 返回的令牌可 disconnect,同次派发中断开尚未执行的监听器也应生效。 capture = root.on("click", model.capture, "capture") target = button.on("click", model.target) bubble = root.on("click", model.bubble) page = Page() page.render(root)