61 lines
3.6 KiB
Plaintext
61 lines
3.6 KiB
Plaintext
// 业务对象与出现位置生命周期分离:同一 child 在根中出现两次,每次都获得独立 Mount 和通知。
|
|
// 普通数据变化不会重新挂载;页面关闭时子项先卸载,父项随后卸载,旧 Mount 不因重开而复活。
|
|
// order 是统一时序,mounted/unmounted 是子项次数;latest 保存最近通知的实际 Mount。
|
|
class LifecycleLog {
|
|
// order/mounted/unmounted/latest 为可写 state,四个顺序字段为 Number;构造参数按这里的字段次序传入。
|
|
order: Object
|
|
mounted: Object
|
|
unmounted: Object
|
|
parentMounted: Number
|
|
childMounted: Number
|
|
parentUnmounted: Number
|
|
childUnmounted: Number
|
|
latest: Object
|
|
}
|
|
// 共享文字用 log 记录两个出现位置,源钩子接收的是当前具体 Mount。
|
|
class WatchedText: TextBlock {
|
|
log: LifecycleLog
|
|
// 记录顺序和次数,保存 Mount 并修改原文字;运行时在回调后重新收敛才发布。
|
|
function onMount(self: WatchedText, mount: Mount): Unit {
|
|
// 宿主为 child 的每个新出现分别调用;同一 self 会收到两次通知,但传入的是两个不同 Mount。
|
|
self.log.order.increment()
|
|
self.log.mounted.increment()
|
|
self.log.childMounted = self.log.order.value
|
|
// 保存最近一次参数供 Console 查询,后一次通知会覆盖前一次;mounted 累计值则保留两次调用。
|
|
// latest.value 强持有这个 Mount 供观察,不使已卸载 Mount 复活;Mount 到 Page/desktop 的反向关系仍为弱引用。
|
|
self.log.latest.set(mount)
|
|
self.setText("同一个对象,两个独立挂载位置")
|
|
}
|
|
// 记录已经脱离的出现位置;保留 Mount 可查询 mounted,但不能再当有效 bounds 使用。
|
|
function onUnmount(self: WatchedText, mount: Mount): Unit {
|
|
// 展示树移除此出现时由宿主调用,不能通过再次 setText 或保存 mount 让已经卸载的出现重新生效。
|
|
self.log.order.increment()
|
|
self.log.unmounted.increment()
|
|
self.log.childUnmounted = self.log.order.value
|
|
self.log.latest.set(mount)
|
|
}
|
|
}
|
|
// 父容器也记录钩子序号,便于对比挂载与子先父后的卸载顺序。
|
|
class WatchedColumn: Column {
|
|
log: LifecycleLog
|
|
// 记录父挂载顺序,不修改容器结构;子项随后各自执行通知。
|
|
function onMount(self: WatchedColumn, mount: Mount): Unit {
|
|
// 父 Mount 建立后的业务通知,只改日志;初始父通知先于下方两个 child 出现的通知。
|
|
self.log.order.increment()
|
|
self.log.parentMounted = self.log.order.value
|
|
}
|
|
// 父卸载时子项卸载已完成,序列号应位于所有子项通知之后。
|
|
function onUnmount(self: WatchedColumn, mount: Mount): Unit {
|
|
// 对整页的卸载,两个子出现先各计一次,父回调最后把当前总序号写入 parentUnmounted。
|
|
self.log.order.increment()
|
|
self.log.parentUnmounted = self.log.order.value
|
|
}
|
|
}
|
|
// 多个 state 容器分别保存计数/最后 Mount,root 最后参数是源 log 字段,前面才是可变视觉子项。
|
|
log = LifecycleLog(ui.state(0), ui.state(0), ui.state(0), 0, 0, 0, 0, ui.state(0))
|
|
child = WatchedText("等待挂载", 2, log)
|
|
// 两个 child 参数是同一对象引用;新增 log 字段位于所有原生视觉子项之后,不会被安排成额外孩子。
|
|
root = WatchedColumn(24, 16, child, child, TextBlock("挂载次数"), ui.textOf(log.mounted, "value"), TextBlock("卸载次数"), ui.textOf(log.unmounted, "value"), log)
|
|
page = Page()
|
|
page.render(root)
|