将分布式 child 附加到 Polymer 中的 <content> 元素

Append distributed child to <content> element in Polymer

我有一个简单的聚合物元素:

<link rel="import" href="bower_components/polymer/polymer.html">


<dom-module id="observing-test">
  <template>
    <p>This is the title:</p>
    <content id="top" select="#title"></content>
    <p>This is the content:</p>
    <content id="bottom" select="#content"></content>
  </template>

  <script>
    Polymer( {
      is: 'observing-test',

      ready: function(){
        console.log("Ready!");

        Polymer.dom( this.$.top ).observeNodes( function( info ) {
          console.log(" TOP CHANGED!", info );
        });

        Polymer.dom( this.$.bottom ).observeNodes( function( info ) {
          console.log(" BOTTOM CHANGED!", info );
        });
      },

      attached: function(){
        console.log("Attached!");
        OT = this;
      }

    })
  </script>
</dom-module>

基本用法:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="description" content="The basic page">
  <meta name="author" content="Tony Mobily">
  <title>The title</title>
  <link rel="import" href="test-component.html">
</head>

<body>

<observing-test>
  <div id="title"><p>TITLE!</p></div>
  <div id="content"><p>CONTENT!</p></div>
</observing-test>

</body>

现在,添加到 #top#bottom 的任何内容都会被观察到。

那么,如何将 child 附加到 #top <content> 元素以便触发观察者?

如果我从本地DOM(从控制台)到达元素:MAYBE = Polymer.dom( OT ).children[0](这将是<div id="title">,然后是Polymer.dom( MAYBE ) .appendChild( document.createElement( 'p' ) ),新元素得到添加到 <div>。但是,观察者不会被触发(因为我将 child 添加到 <div> 而不是 <div> 的 parent],我想这就是正在观看的内容。)

所以问题:

  • <content> 是一个 DOM 插入点(我不会尝试详细解释它是什么,Polymer's dev guide 比我做得更好)。基本上,组件的每个与 <content> 节点的 select 查询匹配的 DOM 子组件都将被插入其中。

    因此,要在 <content> 节点中插入另一个子节点,您必须添加一个与其 select 查询相匹配的子节点到您的组件的灯 DOM.

    为此,您应该将 select 查询更改为针对 ID 以外的内容(即 class 或属性),如下所示:

在您元素的 dom-模块中:

 <content id="top" select=".title"></content>

用法:

 <observing-test id="ot">
   <p class=".title">TITLE!</p>
   <div id="content"><p>CONTENT!</p></div>
 </observing-test>

 var newTitleNode = document.createElement( 'p' );
 newTitleNode.className = "title";
 Polymer.dom( this.$.ot ).appendChild( newTitleNode );
  • Polymer的observeNodes用于检测局部DOM插入点中节点的addition/removal。您在这里所做的是将一个节点附加到一个轻 DOM 节点,该节点本身已插入 content 插入点,您并不是直接插入另一个节点。我相信这就是您没有收到通知的原因。

希望这对你有帮助,某个地方的人可能比我解释得更好。

同时发布我自己的答案,这是由 Vincent 提供的(谢谢!)

如果你有这样的元素:

    <link rel="import" href="bower_components/polymer/polymer.html">
    <dom-module id="observing-test">
      <template>
        <p>This is the list of lines:</p>
        <content id="c" select=".line"></content>
      </template>

      <script>
        Polymer( {
          is: 'observing-test',

          ready: function(){
            console.log("Ready!");

            Polymer.dom( this.$.c ).observeNodes( function( info ) {
              console.log("CHANGED!", info );
            });
          },

          attached: function(){
            console.log("Attached!");
            // GLOBAL, so that we can play we it in the console
            OT = this;
          }

        })
      </script>
    </dom-module>

请记住,复合 DOM 是本地 DOM 的结果,解析了 <content> 个标签。
因此,为了将 "add" 元素替换为带有 select<content> 元素,您需要将元素添加到将与 <content>的选择。
例如,如果您的页面包含:

<observing-test>
  <p>Some content</p>
  <p class="line">Moved line 1</p>
  <p class="line">Moved line 2</p>
  <hr>
  <p class="line">Moved line 3</p>
</observing-test>

如果您随后创建一个元素:

p = document.createElement('p')
p.appendChild(   document.createTextNode('text')   )
p.className = 'line'

并将其添加到灯光中 DOM:

Polymer.dom( OT ).appendChild( p )

<content> 元素上的观察者被触发。 请注意,您必须事先分配class。如果你这样做:

p = document.createElement('p')
p.appendChild(   document.createTextNode('text')   )

然后你追加 child:

Polymer.dom( OT ).appendChild( p )

只有然后你添加正确的class到元素:

p.className = 'line'

回调没有被触发。

原来的问题并不是 "work" 因为过滤器是基于 ID 的。因此,只有一个元素会匹配——因此被 <content>.

选择