从光DOM移动元件ShadowDOM而不disconnectedCallback

问题描述 投票:2回答:1

我不知道如果我在正确的轨道上

目的:必须确保所有元素在shadowDOM结束

所以手动创建的HTML文件

<cardts-pile>
  <cardts-card>A</cardts-card>
  <cardts-card>B</cardts-card>
</cardts-pile>

<cardts-pile>的lightDOM创建卡

如果我然后将它们移到shadowDOM(ofcourse):

<cardts-card>从DOM(触发disconnectedCallback())除去 ►<cardts-card>再次加入(触发connectedCallback()

[见的console.log上运行代码片段如下]

我在card.connectedCallback()更看中码 在“重新连接”它基本上是再次引发了完全相同的代码。

问题

  1. 是否有可能移动节点没有DOM的变化?
  2. 有没有开箱即用的代码,以检查是否已有<cardts-card>只是被移动, 所以connectedCallback知道它并不需要再次运行代码。
  3. 我应该做不同的东西, 使这些lightDOM元素shadowDOM结束立刻?

customElements.define('cardts-pile', class extends HTMLElement {
  constructor(){
    super();
    this.attachShadow({mode: 'open'}).innerHTML='<slot></slot>';
  }
  connectedCallback() {
    console.log('connect pile');
  }
});

customElements.define('cardts-card', class extends HTMLElement {
  constructor(){
    super();
    this.attachShadow({mode: 'open'}).innerHTML='<slot></slot>';
  }
  connectedCallback() {
    console.log('connect card',this.innerText);
    if (!this.getRootNode().host) // not in shadowDOM
       this.parentNode.shadowRoot.insertBefore(this,null);//or appendChild
  }
  disconnectedCallback() {
    console.log('disconnect card',this.innerText);
  }
});
<cardts-pile>
  <cardts-card>A</cardts-card>
  <cardts-card>B</cardts-card>
</cardts-pile>
javascript web-component shadow-dom custom-element native-web-component
1个回答
1
投票

是否有可能移动节点没有DOM的变化?

否(据我了解阴影DOM)。

有没有开箱即用的代码检查,如果现有的只被感动?

我会用一个布尔标志:

connectedCallback() {
    if ( !this.connected )
        console.log( 'creation' )
    else {
        console.log( 'move' )
    this.connected = true   
}

(或者在disconnectedCallack

customElements.define('cardts-pile', class extends HTMLElement {
    constructor(){
        super();
        this.attachShadow({mode: 'open'}).innerHTML='<slot></slot>';
        this.shadowRoot.addEventListener( 'slotchange', ev => {      
            let node = this.querySelector( 'cardts-card' )
            node && this.shadowRoot.append( node )
        })
    }
    connectedCallback() {
        console.log('connect pile');
    }
});
    
customElements.define('cardts-card', class extends HTMLElement {
    constructor(){
        super();
        this.attachShadow({mode: 'open'}).innerHTML='<slot></slot>';
    }
    connectedCallback() {
        if ( !this.connected )
            console.log( this.innerText + ' created' )
        else 
            console.log( this.innerText + ' moved' )
        this.connected = true 
    }
    disconnectedCallback() {
        if ( !this.moved )
            console.log( 'moving ' + this.innerText );
        else 
            console.log( 'really disconnected' )
        this.moved = true
    }
});
<cardts-pile>
  <cardts-card>A</cardts-card>
  <cardts-card>B</cardts-card>
</cardts-pile>

我应该做不同的东西?

你可以代替定义或升级<cardts-card>后才未知元素被移动,如果可能的话,尽管我不认为这是一个很好的做法,除非你可以控制整个执行时间,例如与whenDefined()或有序HTML和Javascript代码:

customElements.define('cardts-pile', Pile)
customElements.whenDefined('cardts-pile').then(() => 
    customElements.define('cardts-card', Card)
)

在下面的例子中,你(这取决于它们之间的关系)之前或类Pile后定义类Card

class Card extends HTMLElement {
    constructor(){
        super()
        this.attachShadow({mode: 'open'}).innerHTML='<slot></slot>'
    }
    connectedCallback() {
        console.log(this.innerText + ' connected')
    }
    disconnectedCallback() {
         console.log(this.innerText + ' disconnected')
    }
}

class Pile extends HTMLElement {
    constructor() {
        super()
        this.attachShadow({mode: 'open'})
    }
    connectedCallback() {
        console.log('connect pile')
        this.shadowRoot.append(...this.querySelectorAll('cardts-card'))
    }
}

window.onload = () => customElements.define('cardts-pile', Pile)
customElements.whenDefined('cardts-pile').then(() => 
    customElements.define('cardts-card', Card)
)
<cardts-pile>
  <cardts-card>A</cardts-card>
  <cardts-card>B</cardts-card>
</cardts-pile>
© www.soinside.com 2019 - 2024. All rights reserved.