gpt4 book ai didi

javascript - 在不调用 connectedCallback 的情况下交换 "Custom Element"

转载 作者:行者123 更新时间:2023-11-27 23:11:14 28 4
gpt4 key购买 nike

我正在创建一个需要在列表中切换元素的选举应用程序。我有以下自定义元素 Web 组件。为了简洁起见,我已经从类中删除了不相关的函数。

// 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 元素添加到 Position 和 Candidate 元素中。

例如交换后的结果应该是:

<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 模板,这样我就不需要在 connectedCallback 中添加元素了?如果没有,我如何在不携带所有额外元素的情况下有效交换?请注意,我不想使用 jQuery,因为我想要一个轻量级应用程序。

我已经看到了这个但它不起作用,因为它最终调用了 connectedCallback 并插入了 How to swap DOM child nodes in JavaScript?

最佳答案

有几种解决方法:

  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>

  1. 您可以使用 CSS flexbox 和 CSS order 属性来更改元素的顺序,而无需使用 insertBefore()

关于javascript - 在不调用 connectedCallback 的情况下交换 "Custom Element",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45890597/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com