<template if='...'> 在 Dart Polymer 中最终实例化为 DOM 时如何设置回调

How to set callback when <template if='...'> is finally instantiated into DOM in Dart Polymer

我有这样的元素:

<polymer-element name="my-app">
  <template>
    <template id="page_template" if="{{authenticated}}">
      <my-page id="page"></my-page>
    </template>
  </template>
  <script src="..."></script>
</polymer-element>

当 id=="page_template" 的模板实际实例化到 DOM.

时,我需要执行一些初始化

我试过做类似的东西:

authenticatedChange(_) {
  if(authenticated)
    shadowRoot.querySelector('#page').addEventListener(...);
}

但是得到了这个:

Exception: The null object does not have a method 'addEventListener'

看起来 'page' 还不存在。 然后我尝试将创建事件放到事件循环的末尾:

authenticatedChange(_) {
  if(authenticated)
    Timer.run(()=>shadowRoot.querySelector('#page').addEventListener(...));
}

这行得通,但我怀疑它是不是一个好的样式,因为不能保证它实际上会被创建到那个步骤(它完全依赖于实现),因为没有像 Future 或回调这样的显式依赖实例化模板时绑定到事件。

那么问题来了,这样的事件存在吗?我找到的只是 'template-bound',但是这段代码

$['page_template'].on['template-bound'].listen((_)=>print("template-bound!"));

在 MyApp.created() 中执行,在控制台中产生静默。

如何将我的代码绑定到 instantiate/deinstantiate 事件?

onMutation($['page_template']).asStream().listen((_)=>print("mutated."));

我也没用。

$['page_template'].shadowRootnull,所以我根本无法绑定到它的突变。

我自己还不需要 template-bound 事件,但这应该是正确的方法。如果 $['page_template'] returns null 此代码可能在错误的位置。 MyApp.created() 是大多数代码的错误位置,尤其是与 Polymer 相关的所有代码。如果您覆盖 ready() 方法并将您的代码放在那里它应该可以工作。

您可以在影子根上使用变异观察器来执行此操作,在您的 ready 方法中添加如下内容:

new MutationObserver((changes, _) {
    print(changes.any((record) => record.addedNodes.any(
        (node) => node is Element && node.id == 'page')));
})..observe(this.shadowRoot, childList: true);

这将在添加页面时打印 true。这样做的效率显然会根据阴影 dom 变化的频率而有所不同。如果您只想获取本地更改,请将模板包装在另一个节点中并监听它。