【问题标题】:ShadowRoot not finding elements inside template repeat in PolymerShadowRoot 没有在 Polymer 中的模板重复中找到元素
【发布时间】:2013-09-08 16:55:22
【问题描述】:

我在访问 Polymer 元素的 shadowDom 时遇到问题。这是元素的(截断的)代码:

<polymer-element name="word-element" attributes="chars">
  <template>
    <h2>Drag and drop the letters to form anagrams</h2>
    <div id='container'>
      <div class="char" draggable="true">a</div>
      <div class="char" draggable="true">b</div>
      <div class="char" draggable="true">c</div>
      <br>
      <br>
      <template repeat="{{chars}}">
        <div class="char" draggable="true">{{}}</div>
      </template>
    </div>
  </template>
</polymer-element>

Dart 代码如下所示:

@CustomTag("word-element")
class WordElement extends PolymerElement with ObservableMixin {
  @observable List chars;

inserted() {
    var charDivs = this.shadowRoot.queryAll('.char');
    print(charDivs.length);
}

charDivs.length 总是返回 3,计算我硬编码到 &lt;template&gt; 中的 3 个 &lt;div&gt;s。使用shadowRoot 不会发现在&lt;template repeat="{{chars}}"&gt; 代码中创建的任何div。任何想法为什么会出现这种情况?

此外,当我将样式应用于 char 类的元素时,样式将应用于所有 &lt;div&gt;s,包括在repeat 中创建的样式。但是使用shadowRoot 只会返回硬编码的div。

【问题讨论】:

    标签: dart polymer


    【解决方案1】:

    您可以为此使用 Mutation Observers。正如其他地方所提到的,模板绑定和重复是在创建和插入自定义元素之后的某个时间异步发生的。

    当节点或其子树被修改时,使用 Mutation Observer 得到通知。

    这是 Dart 代码:

    import 'package:polymer/polymer.dart';
    import 'dart:html';
    import 'dart:async';
    
    @CustomTag("my-element")
    class MyElement extends PolymerElement with ObservableMixin {
      final List<String> timestamps = toObservable([]);
      MutationObserver observer;
    
      created() {
        super.created();
    
        observer = new MutationObserver(_onMutation);
        observer.observe(shadowRoot.query('#timestamps'), childList: true, subtree: true);
    
        new Timer.periodic(const Duration(seconds: 1), (t) {
          timestamps.add(new DateTime.now().toString());
        });
      }
    
      // Bindings, like repeat, happen asynchronously. To be notified
      // when the shadow root's tree is modified, use a MutationObserver.
    
      _onMutation(List<MutationRecord> mutations, MutationObserver observer) {
        print('${mutations.length} mutations occurred, the first to ${mutations[0].target}');
      }
    }
    

    这是 HTML 代码:

    <polymer-element name="my-element">
      <template>
        <ul id="timestamps">
          <template repeat="{{ts in timestamps}}">
            <li>{{ts}}</li>
          </template>
        </ul>
      </template>
      <script type="application/dart" src="my_element.dart"></script>
    </polymer-element>
    

    【讨论】:

    • 非常好的解决方案。谢谢。
    【解决方案2】:

    尝试将查询放入Timer.run

    Timer.run(() {
      print("timer");
      var charDivs = this.shadowRoot.queryAll('.char');
      print("charsDiv: ${charDivs.length}");
    });
    

    然后,当我用一个列表填充chars="{{someList}}" 属性时,例如:['d','e','f'],我会返回完整的集合(即length=6)。

    这是一个演示完整代码的要点:https://gist.github.com/chrisbu/6488370

    【讨论】:

    • 我们是否保证绑定在下一个事件循环中全部完成?
    • 这是一个公平的问题,我更喜欢你的回答。
    • 克里斯,我接受了赛斯的回答,但你的作品也是如此。我唯一的问题是使用Timer() 并不能保证,尽管它可能在大多数情况下都有效。
    • 是的,我对这个警告也很满意。
    猜你喜欢
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多