2

我創建一個應用程序的選舉,這將需要在列表中的開關元件。我有以下自定義元素Web組件。爲了簡潔起見,我修剪了課堂中不相關的功能。交換「自定義元素」,而無需調用connectedCallback

// Position 
// --------------------------------------- 
class Position extends HTMLElement { 
    constructor(title) { 
     super(); 
     this.title = title 
    } 

    connectedCallback() { 
     this.className = "portlet"; 
     // Copy the HTML template 
     var template = document.querySelector("#template-e-position"); 
     this.appendChild(document.importNode(template.content, true)); 
     // Create the title tag 
     var title = this.querySelector(".title"); 
     title.innerHTML = this.title; 
     // Create event listener for swap links 
     this.querySelector(".moveUp").addEventListener("click", function(e) { 
      swapWithPrevSibling(that); 
     }); 
     this.querySelector(".moveDown").addEventListener("click", function(e) { 
      swapWithNextSibling(that); 
     }); 
    } 
} 
customElements.define('e-position', Position); 

// Candidate 
// --------------------------------------- 
class Candidate extends HTMLElement { 
    constructor(name) { 
    super(); 
    this.name = name; 
    } 
    connectedCallback() { 
     // Copy the HTML template 
     var template = document.querySelector("#template-e-candidate"); 
     this.appendChild(document.importNode(template.content, true)); 
     // Create the title tag 
     var name = this.querySelector(".name"); 
     name.innerHTML = this.name; 
     // Create event listener for delete link 
     var a = this.querySelector("a.delete"); 
     var that = this; 
     a.addEventListener('click', function(e) { return that.delete(e) }, false); 
    } 

    delete(event) { 
     deleteNode(this); 
    } 

} 
customElements.define('e-candidate', Candidate); 

我有交換功能:

function swapWithPrevSibling (elm) { 
    elm.parentNode.insertBefore(elm,elm.previousSibling) 
} 

function swapWithNextSibling (elm) { 
    elm.parentNode.insertBefore(elm.nextSibling,elm) 
} 

我用下面的模板建立自定義元素:

<template id="template-e-position"> 
    <div class="header"> 
     <span class="title"></span> 
     <div class="edit-menu"> 
      <a class="moveUp">&uarr;</a> 
      <a class="moveDown">&darr;</a> 
      <a class="delete">X</a> 
     </div> 
    </div> 
    <div class="candidate-list"> 
    </div> 
    <form class="add-candidate"> 
     <input type="text" /> 
     <input type="submit" value="Add candidate"> 
    </form> 
</template> 

<template id="template-e-candidate"> 
    <span class="name"></span> 
    <div class="edit-menu"> 
     <a class="moveUp">&uarr;</a> 
     <a class="moveDown">&darr;</a> 
     <a class="delete">X</a> 
    </div> 
</template> 

因爲我從HTML模板創建自定義元素,我需要克隆的connectedCallback()模板(因爲在構造函數中V1是不允許添加子)。這樣做的結果是,當我打電話交換功能,在列表中的「位置」,它結束了再克隆的模板和不必要的DOM元素到兩個位置和候選元素加入。

例如,交換後的結果應該是:

<e-position title="Vice-President" class="portlet"> 
    <div class="header"> 
     <span class="title">Vice-President</span> 
     <div class="edit-menu"> 
      <a class="moveUp">↑</a> 
      <a class="moveDown">↓</a> 
      <a class="delete">X</a> 
     </div> 
    </div> 
    <div class="candidate-list"> 
<e-candidate> 
    <span class="name">Evan</span> 
    <div class="edit-menu"> 
     <a class="moveUp">↑</a> 
     <a class="moveDown">↓</a> 
     <a class="delete">X</a> 
    </div> 
</e-candidate> 
<e-candidate> 
    <span class="name">Steph</span> 
    <div class="edit-menu"> 
     <a class="moveUp">↑</a> 
     <a class="moveDown">↓</a> 
     <a class="delete">X</a> 
    </div> 
</e-candidate> 
    </div> 
    <form class="add-candidate"> 
     <input type="text"> 
     <input value="Add candidate" type="submit"> 
    </form> 
</e-position> 

但它最終被一個混亂:

<e-position title="Vice-President" class="portlet"> 
    <div class="header"> 
     <span class="title">Vice-President</span> 
     <div class="edit-menu"> 
      <a class="moveUp">↑</a> 
      <a class="moveDown">↓</a> 
      <a class="delete">X</a> 
     </div> 
    </div> 
    <div class="candidate-list"> 
    <e-candidate> 
    <span class="name">Evan</span> 
    <div class="edit-menu"> 
     <a class="moveUp">↑</a> 
     <a class="moveDown">↓</a> 
     <a class="delete">X</a> 
    </div> 

    <span class="name"></span> 
    <div class="edit-menu"> 
     <a class="moveUp">↑</a> 
     <a class="moveDown">↓</a> 
     <a class="delete">X</a> 
    </div> 
    </e-candidate><e-candidate> 
    <span class="name">Steph</span> 
    <div class="edit-menu"> 
     <a class="moveUp">↑</a> 
     <a class="moveDown">↓</a> 
     <a class="delete">X</a> 
    </div> 

    <span class="name"></span> 
    <div class="edit-menu"> 
     <a class="moveUp">↑</a> 
     <a class="moveDown">↓</a> 
     <a class="delete">X</a> 
    </div> 
    </e-candidate> 
    </div> 
    <form class="add-candidate"> 
     <input type="text"> 
     <input value="Add candidate" type="submit"> 
    </form> 

    <div class="header"> 
     <span class="title"></span> 
     <div class="edit-menu"> 
      <a class="moveUp">↑</a> 
      <a class="moveDown">↓</a> 
      <a class="delete">X</a> 
     </div> 
    </div> 
    <div class="candidate-list"> 
    </div> 
    <form class="add-candidate"> 
     <input type="text"> 
     <input value="Add candidate" type="submit"> 
    </form> 
</e-position> 

有沒有更好的方式來克隆HTML模板,以便我不「T需要增加在connectedCallback元素呢?如果不是,我怎樣纔能有效地交換,而不帶來所有額外的元素?請注意,我不想使用jQuery,因爲我想要一個輕量級應用程序。

我已經看到了這一點,這是行不通的,因爲它最終調用connectedCallback和插入How to swap DOM child nodes in JavaScript?

回答

2

有幾種解決方案:

  1. 您可以使用一個標誌,看它是否是第一個回調被調用的時間,並且只有當標誌還沒有設置時才插入模板。

customElements.define('e-candidate', class extends HTMLElement { 
 
    connectedCallback() { 
 
    if (!this.init) { 
 
     var template = document.querySelector('#template-e-candidate') 
 
     this.appendChild(template.content.cloneNode(true)) 
 
     this.querySelector('.moveUp') 
 
      .onclick =() => 
 
       this.previousElementSibling && this.parentElement.insertBefore(this, this.previousElementSibling) 
 
     this.init = true 
 
    } 
 
    } 
 
})
e-candidate { display:block }
<template id="template-e-candidate"> 
 
    <slot></slot> 
 
    <button class="moveUp">&uarr;</button> 
 
</template> 
 

 
<e-candidate>First</e-candidate> 
 
<e-candidate>Second</e-candidate>

  • 可以使用CSS flexbox與CSS order屬性來改變元素的順序,而無需使用insertBefore()
  • +0

    的標誌是一個好主意。最後我用一個自Flexbox,就不能在我的項目的更大範圍使用。謝謝! – Mike