How to distribute (insert) content nodes programma

2019-03-17 00:59发布

Is there a way to programmatically distribute (insert) content from lightDOM to ShadowDOM?

I would like to wrap every single child node into an element. For example :

<my-list>
  <span>first element</span>
  <div>second element</div>
  <a>third element</a>
</my-link>

to be distributed as

<my-list>
  <ul>
    <li>
      <span>first element</span>
    </li>
    <li>
      <div>second element</div>
    </li>
    <li>
      <a>third element</a>
    </li>
  </ul>
</my-link>

I need it not only to render that way, but also delegate entire HTML behavior (bindings, events, etc..) as each distributed node may contain entire app.

I have tried appending <content select=":nth-child(..)"> elements to template on attached callback

attached: function(){
    //ensure any element upgrades have been processed
    this.async(function asyncAttached(){
        var list = this.$.container;
        this.children.array().forEach(function(child, childNo){
            var li = document.createElement("LI");
            console.log(list, li, child);
            li.innerHTML = '<content select=":nth-child('+childNo+')"></content>';
            list.appendChild(li);
        });
    });
}

But it does not work (probably because content was already distributed).

Fiddle here

In general what I would like to achieve is something like http://jsbin.com/hegizi/3/edit, but without hard-coding class names, and make it work with variable number of child nodes.

What is more, it seems, that :nth-child is not supported natively: https://github.com/Polymer/polymer/issues/470

2条回答
2楼-- · 2019-03-17 01:48

Composition is something Shadow DOM is designed for. If that spec bug gets fixed, the best way to do this would be interesting tricks with <content select=":nth-child(...)"> in a <template repeat>. Since you can't (currently) use :nth-child, you could instead use the distributed nodes and data-binding to wrap the content:

<template repeat="{{node in nodes}}">
  <li>
    <html-echo html="{{node.outerHTML}}"></html-echo>
  </li>
</template>
<content id="c" select="*"></content>

nodes is generated from something like:

this.nodes = Array.prototype.slice.call(this.$.c.getDistributedNodes());

I'm using <html-echo> from this post: https://stackoverflow.com/a/22208332/274673

Working demo: http://jsbin.com/mamawugo/2/edit

查看更多
何必那么认真
3楼-- · 2019-03-17 01:52

There is quite old issue at W3C Bugzilla: #18429 - [Shadow]: Specify imperative API for node distribution

But as for now, there is nothing in spec about that.

查看更多
登录 后发表回答