是否可以保留自定义元素的内部html?

时间:2018-02-12 01:43:24

标签: javascript html web-component native-web-component

使用自定义元素,我想在自定义元素中设置元素的样式,但是当我定义元素时,阴影dom之外的所有内容都会消失。

如何将内容从元素移动到阴影dom?我已经在阴影中有一个包装元素(<div class="wrapper">),但是尝试使用

wrapper.innerHTML = this.innerHTML;

不起作用。

HTML

<site-card>
  <section title>
    ...
  </section>
  <section body>
    ...
  </section>
  <section actions>
    <button class="modern small">Action</button>
    <button class="modern small">Action 2</button>
  </section>
</site-card>

JS

"use strict";
class cardElement extends HTMLElement {
    constructor() {
        super();
        var shadow = this.attachShadow({mode: 'open'});
        var wrapper = document.createElement('div');
        wrapper.setAttribute('class','wrapper');
        wrapper.innerHTML = this.innerHTML;
        var style = document.createElement('style');
        style.textContent = ... /* CSS removed to shorten. */
        shadow.appendChild(style);
        shadow.appendChild(wrapper);
    };
};
customElements.define('site-card', cardElement);

2 个答案:

答案 0 :(得分:1)

如果要从自定义元素外部控制CSS,则只需使用triggers="mouseenter:mouseleave click"(click)将子项嵌入到插槽中,但将CSS控件留在元素外部。

&#13;
&#13;
<slot>
&#13;
<slot>
&#13;
class cardElement extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow({mode: 'open'});
    var wrapper = document.createElement('slot');
    var style = document.createElement('style');
    style.textContent = `
    [title] {
      background-color: #060;
      color: #FFF;
    }
    [body] {
      background-color: #600;
      color: #FFF;
    }
    [actions] {
      background-color: #006;
      color: #FFF;
    }
    `;
    shadow.appendChild(style);
    shadow.appendChild(wrapper);
  };
};
customElements.define('site-card', cardElement);
&#13;
&#13;
&#13;

如果要从元素内部控制CSS,则需要迁移子元素。但是这可以在构造函数中完成。 This section of the spec解释了构造函数的限制。

您需要移动[title] { background-color: #0F0; color: #000; } [body] { background-color: #F00; color: #000; } [actions] { background-color: #00F; color: #000; }

中的孩子

&#13;
&#13;
<site-card>
  <section title>
    This is the title
  </section>
  <section body>
    This is the body
  </section>
  <section actions>
    <button class="modern small">Action</button>
    <button class="modern small">Action 2</button>
  </section>
</site-card>
&#13;
connectedCallback
&#13;
class cardElement extends HTMLElement {
  constructor() {
    super();
    var shadow = this.attachShadow({mode: 'open'});
    this._wrapper = document.createElement('div');
    var style = document.createElement('style');
    style.textContent = `
    [title] {
      background-color: #060;
      color: #FFF;
    }
    [body] {
      background-color: #600;
      color: #FFF;
    }
    [actions] {
      background-color: #006;
      color: #FFF;
    }
    `;
    shadow.appendChild(style);
    shadow.appendChild(this._wrapper);
  };
  
  connectedCallback() {
    while(this.firstElementChild) {
      this._wrapper.appendChild(this.firstElementChild);
    }
  }
};
customElements.define('site-card', cardElement);
&#13;
&#13;
&#13;

  

我建议避免使用[title] { background-color: #0F0; color: #000; } [body] { background-color: #F00; color: #000; } [actions] { background-color: #00F; color: #000; },因为这会消除可能已经存在的任何事件处理程序等。根据直接儿童的数量,它实际上可能会更慢。它也可能搞乱任何可能是自定义元素的孩子。

答案 1 :(得分:0)

稍后您应该在window.onload

中执行此操作
class cardElement extends HTMLElement {
    constructor() {
        super();
        var shadow = this.attachShadow({ mode: 'open' });
        var wrapper = document.createElement('div');
        wrapper.setAttribute('class', 'wrapper');
        window.onload = () => {
            wrapper.innerHTML = this.innerHTML;
        };
        var style = document.createElement('style');
        style.textContent = ... /* CSS removed to shorten. */
        shadow.appendChild(style);
        shadow.appendChild(wrapper);
    }
};
customElements.define('site-card', cardElement);