动态创建按钮时如何交变量?
How to hand over variables when creating buttons dynamically?
我目前正在编写 WhatsApp-Chat-Analyzer。因此,我必须遍历聊天的参与者并创建每个代表一个参与者的按钮。创建这些按钮时,必须将参数或变量移交给一个函数,该函数然后执行进一步处理 parameters/variables 的代码。
但是,无论我尝试什么,单击按钮时调用的函数都没有使用正确的变量;它总是使用数组中第一个用于在 for 循环中循环的数组。
同时,在创建按钮时打印出变量确实工作正常 - 所有唯一变量都被打印出来,而不仅仅是第一个。
据我所知,所有这些都表明示波器有问题。
来自 Java,使用 javascript 变量非常令人困惑,因为其中一些看起来是全局的,即使它们是在函数或循环中声明的。这就是为什么我试图封装移交给动态创建的按钮的功能。可悲的是,设置一个函数 returns 另一个函数并移交第一个函数不起作用,尽管它实际上应该起作用。
此外,我知道在这种情况下应该使用 "let" 而不是 "var" 来创建局部变量。
下面的代码代表了我正在做的事情以及到目前为止我尝试过的解决方案。
let participantsArray = ["Fred", "Kim", "Donald", "Xi"];
function displayParticipants() {
let parentElementChatSection = document.getElementById("participantButtons");
let participants = participantsArray;
for (let participant of participants) {
participantsElement(participant, parentElementChatSection);
}
}
function participantsElement(participant, parentElement) {
let participantDiv1 = createHTMLElement(parentElement, "div", "participantDiv");
let button = createButtonElement(participantDiv1, participant, "participantButton", (function(variable) {
return function() {
handleParticipant(variable);
};
})(participant));
}
function createButtonElement(parentElement, text, className,
functionToExecute) {
let element = document.createElement("input");
element.type = "button";
element.value = text;
element.className = className + "Hidden";
element.id = className + "Hidden";
element.onclick = functionToExecute;
parentElement.appendChild(element);
let label = document.createElement("label");
label.htmlFor = element.id;
label.className = className;
parentElement.appendChild(label);
element.style.display = "none";
let textElement = createTextElement(label, text, className + "Text");
return [element, label, textElement];
}
function handleParticipant(participant) {
alert(participant);
}
function createTextElement(parentElement, text, className) {
let element = document.createElement("p");
let elementText = document.createTextNode(text);
element.className = className;
element.appendChild(elementText);
parentElement.appendChild(element);
return element;
}
function createHTMLElement(parentElement, type, className) {
let element = document.createElement(type);
element.className = className;
parentElement.appendChild(element);
return element;
}
displayParticipants();
.participantButtonText {
box-shadow: 0px 5px 10px 1px rgba(18, 140, 126, 0.25);
padding: 0.5em;
margin: 0.5em;
background-color: #128C7E;
color: white;
}
.participantButtonText:hover {
background-color: #075E54;
}
.participantDiv {
position: relative;
float: left;
height: auto;
flex-shrink: 1;
flex-grow: 1;
min-width: 30px;
transition: 0.1s;
transition-property: background-color, color, transform;
text-align: center;
}
#participantButtons {
width: 100%;
clear: both;
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
}
.displayedParticipantButton {
background-color: rgb(172, 117, 0);
}
.displayedParticipantButton:hover {
background-color: rgb(172, 92, 0);
}
<div id="participantButtons">
</div>
如果代码工作正常,每个按钮都应该存储它所代表的参与者的变量。按下时,按钮应使用预先传递的变量执行函数 "handleParticipant" 并打印出参与者。
最后但同样重要的是;问题的现场演示:
https://jsfiddle.net/Muelli21/21cv7eja/
问题是您在 HTML 中有重复的 ID。这是一个更简单的示例(点击 标签 ,然后观察哪个按钮被点击):
document.querySelectorAll('input').forEach((input) => {
input.onclick = () => console.log(input.value);
});
<input type="button" value="Fred" id="participantButtonHidden"><label for="participantButtonHidden">label</label>
<input type="button" value="Kim" id="participantButtonHidden"><label for="participantButtonHidden">label</label>
for
属性指向要单击的按钮的 ID。但是在任何文档中都应该只有一个特定 ID 的元素。这里发生的是浏览器找到匹配该 ID 的 first 元素,单击它,然后停在那里。但是每个input
都有相同的ID,所以每次都会点击第一个输入。
改用单独的 ID:
element.id = text + "Hidden";
let participantsArray = ["Fred", "Kim", "Donald", "Xi"];
function displayParticipants() {
let parentElementChatSection = document.getElementById("participantButtons");
let participants = participantsArray;
for (let participant of participants) {
participantsElement(participant, parentElementChatSection);
}
}
function participantsElement(participant, parentElement) {
let participantDiv1 = createHTMLElement(parentElement, "div", "participantDiv");
let button = createButtonElement(participantDiv1, participant, "participantButton", (function(variable) {
return function() {
handleParticipant(variable);
};
})(participant));
}
function createButtonElement(parentElement, text, className,
functionToExecute) {
let element = document.createElement("input");
element.type = "button";
element.value = text;
element.className = className + "Hidden";
element.id = text + "Hidden";
element.onclick = functionToExecute;
parentElement.appendChild(element);
let label = document.createElement("label");
label.htmlFor = element.id;
label.className = className;
parentElement.appendChild(label);
element.style.display = "none";
let textElement = createTextElement(label, text, className + "Text");
return [element, label, textElement];
}
function handleParticipant(participant) {
alert(participant);
}
function createTextElement(parentElement, text, className) {
let element = document.createElement("p");
let elementText = document.createTextNode(text);
element.className = className;
element.appendChild(elementText);
parentElement.appendChild(element);
return element;
}
function createHTMLElement(parentElement, type, className) {
let element = document.createElement(type);
element.className = className;
parentElement.appendChild(element);
return element;
}
displayParticipants();
.participantButtonText {
box-shadow: 0px 5px 10px 1px rgba(18, 140, 126, 0.25);
padding: 0.5em;
margin: 0.5em;
background-color: #128C7E;
color: white;
}
.participantButtonText:hover {
background-color: #075E54;
}
.participantDiv {
position: relative;
float: left;
height: auto;
flex-shrink: 1;
flex-grow: 1;
min-width: 30px;
transition: 0.1s;
transition-property: background-color, color, transform;
text-align: center;
}
#participantButtons {
width: 100%;
clear: both;
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
}
.displayedParticipantButton {
background-color: rgb(172, 117, 0);
}
.displayedParticipantButton:hover {
background-color: rgb(172, 92, 0);
}
<div id="participantButtons">
</div>
或者,更优雅地,完全避免 ID,并将点击事件侦听器附加到标签:
let participantsArray = ["Fred", "Kim", "Donald", "Xi"];
function displayParticipants() {
let parentElementChatSection = document.getElementById("participantButtons");
let participants = participantsArray;
for (let participant of participants) {
participantsElement(participant, parentElementChatSection);
}
}
function participantsElement(participant, parentElement) {
let participantDiv1 = createHTMLElement(parentElement, "div", "participantDiv");
let button = createButtonElement(participantDiv1, participant, "participantButton", (function(variable) {
return function() {
handleParticipant(variable);
};
})(participant));
}
function createButtonElement(parentElement, text, className,
functionToExecute) {
let element = document.createElement("input");
element.type = "button";
element.value = text;
element.className = className + "Hidden";
element.id = text + "Hidden";
parentElement.appendChild(element);
let label = document.createElement("label");
label.htmlFor = element.id;
label.className = className;
label.addEventListener('click', functionToExecute);
parentElement.appendChild(label);
element.style.display = "none";
let textElement = createTextElement(label, text, className + "Text");
return [element, label, textElement];
}
function handleParticipant(participant) {
alert(participant);
}
function createTextElement(parentElement, text, className) {
let element = document.createElement("p");
let elementText = document.createTextNode(text);
element.className = className;
element.appendChild(elementText);
parentElement.appendChild(element);
return element;
}
function createHTMLElement(parentElement, type, className) {
let element = document.createElement(type);
element.className = className;
parentElement.appendChild(element);
return element;
}
displayParticipants();
.participantButtonText {
box-shadow: 0px 5px 10px 1px rgba(18, 140, 126, 0.25);
padding: 0.5em;
margin: 0.5em;
background-color: #128C7E;
color: white;
}
.participantButtonText:hover {
background-color: #075E54;
}
.participantDiv {
position: relative;
float: left;
height: auto;
flex-shrink: 1;
flex-grow: 1;
min-width: 30px;
transition: 0.1s;
transition-property: background-color, color, transform;
text-align: center;
}
#participantButtons {
width: 100%;
clear: both;
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
}
.displayedParticipantButton {
background-color: rgb(172, 117, 0);
}
.displayedParticipantButton:hover {
background-color: rgb(172, 92, 0);
}
<div id="participantButtons">
</div>
我目前正在编写 WhatsApp-Chat-Analyzer。因此,我必须遍历聊天的参与者并创建每个代表一个参与者的按钮。创建这些按钮时,必须将参数或变量移交给一个函数,该函数然后执行进一步处理 parameters/variables 的代码。
但是,无论我尝试什么,单击按钮时调用的函数都没有使用正确的变量;它总是使用数组中第一个用于在 for 循环中循环的数组。
同时,在创建按钮时打印出变量确实工作正常 - 所有唯一变量都被打印出来,而不仅仅是第一个。
据我所知,所有这些都表明示波器有问题。
来自 Java,使用 javascript 变量非常令人困惑,因为其中一些看起来是全局的,即使它们是在函数或循环中声明的。这就是为什么我试图封装移交给动态创建的按钮的功能。可悲的是,设置一个函数 returns 另一个函数并移交第一个函数不起作用,尽管它实际上应该起作用。
此外,我知道在这种情况下应该使用 "let" 而不是 "var" 来创建局部变量。
下面的代码代表了我正在做的事情以及到目前为止我尝试过的解决方案。
let participantsArray = ["Fred", "Kim", "Donald", "Xi"];
function displayParticipants() {
let parentElementChatSection = document.getElementById("participantButtons");
let participants = participantsArray;
for (let participant of participants) {
participantsElement(participant, parentElementChatSection);
}
}
function participantsElement(participant, parentElement) {
let participantDiv1 = createHTMLElement(parentElement, "div", "participantDiv");
let button = createButtonElement(participantDiv1, participant, "participantButton", (function(variable) {
return function() {
handleParticipant(variable);
};
})(participant));
}
function createButtonElement(parentElement, text, className,
functionToExecute) {
let element = document.createElement("input");
element.type = "button";
element.value = text;
element.className = className + "Hidden";
element.id = className + "Hidden";
element.onclick = functionToExecute;
parentElement.appendChild(element);
let label = document.createElement("label");
label.htmlFor = element.id;
label.className = className;
parentElement.appendChild(label);
element.style.display = "none";
let textElement = createTextElement(label, text, className + "Text");
return [element, label, textElement];
}
function handleParticipant(participant) {
alert(participant);
}
function createTextElement(parentElement, text, className) {
let element = document.createElement("p");
let elementText = document.createTextNode(text);
element.className = className;
element.appendChild(elementText);
parentElement.appendChild(element);
return element;
}
function createHTMLElement(parentElement, type, className) {
let element = document.createElement(type);
element.className = className;
parentElement.appendChild(element);
return element;
}
displayParticipants();
.participantButtonText {
box-shadow: 0px 5px 10px 1px rgba(18, 140, 126, 0.25);
padding: 0.5em;
margin: 0.5em;
background-color: #128C7E;
color: white;
}
.participantButtonText:hover {
background-color: #075E54;
}
.participantDiv {
position: relative;
float: left;
height: auto;
flex-shrink: 1;
flex-grow: 1;
min-width: 30px;
transition: 0.1s;
transition-property: background-color, color, transform;
text-align: center;
}
#participantButtons {
width: 100%;
clear: both;
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
}
.displayedParticipantButton {
background-color: rgb(172, 117, 0);
}
.displayedParticipantButton:hover {
background-color: rgb(172, 92, 0);
}
<div id="participantButtons">
</div>
如果代码工作正常,每个按钮都应该存储它所代表的参与者的变量。按下时,按钮应使用预先传递的变量执行函数 "handleParticipant" 并打印出参与者。
最后但同样重要的是;问题的现场演示: https://jsfiddle.net/Muelli21/21cv7eja/
问题是您在 HTML 中有重复的 ID。这是一个更简单的示例(点击 标签 ,然后观察哪个按钮被点击):
document.querySelectorAll('input').forEach((input) => {
input.onclick = () => console.log(input.value);
});
<input type="button" value="Fred" id="participantButtonHidden"><label for="participantButtonHidden">label</label>
<input type="button" value="Kim" id="participantButtonHidden"><label for="participantButtonHidden">label</label>
for
属性指向要单击的按钮的 ID。但是在任何文档中都应该只有一个特定 ID 的元素。这里发生的是浏览器找到匹配该 ID 的 first 元素,单击它,然后停在那里。但是每个input
都有相同的ID,所以每次都会点击第一个输入。
改用单独的 ID:
element.id = text + "Hidden";
let participantsArray = ["Fred", "Kim", "Donald", "Xi"];
function displayParticipants() {
let parentElementChatSection = document.getElementById("participantButtons");
let participants = participantsArray;
for (let participant of participants) {
participantsElement(participant, parentElementChatSection);
}
}
function participantsElement(participant, parentElement) {
let participantDiv1 = createHTMLElement(parentElement, "div", "participantDiv");
let button = createButtonElement(participantDiv1, participant, "participantButton", (function(variable) {
return function() {
handleParticipant(variable);
};
})(participant));
}
function createButtonElement(parentElement, text, className,
functionToExecute) {
let element = document.createElement("input");
element.type = "button";
element.value = text;
element.className = className + "Hidden";
element.id = text + "Hidden";
element.onclick = functionToExecute;
parentElement.appendChild(element);
let label = document.createElement("label");
label.htmlFor = element.id;
label.className = className;
parentElement.appendChild(label);
element.style.display = "none";
let textElement = createTextElement(label, text, className + "Text");
return [element, label, textElement];
}
function handleParticipant(participant) {
alert(participant);
}
function createTextElement(parentElement, text, className) {
let element = document.createElement("p");
let elementText = document.createTextNode(text);
element.className = className;
element.appendChild(elementText);
parentElement.appendChild(element);
return element;
}
function createHTMLElement(parentElement, type, className) {
let element = document.createElement(type);
element.className = className;
parentElement.appendChild(element);
return element;
}
displayParticipants();
.participantButtonText {
box-shadow: 0px 5px 10px 1px rgba(18, 140, 126, 0.25);
padding: 0.5em;
margin: 0.5em;
background-color: #128C7E;
color: white;
}
.participantButtonText:hover {
background-color: #075E54;
}
.participantDiv {
position: relative;
float: left;
height: auto;
flex-shrink: 1;
flex-grow: 1;
min-width: 30px;
transition: 0.1s;
transition-property: background-color, color, transform;
text-align: center;
}
#participantButtons {
width: 100%;
clear: both;
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
}
.displayedParticipantButton {
background-color: rgb(172, 117, 0);
}
.displayedParticipantButton:hover {
background-color: rgb(172, 92, 0);
}
<div id="participantButtons">
</div>
或者,更优雅地,完全避免 ID,并将点击事件侦听器附加到标签:
let participantsArray = ["Fred", "Kim", "Donald", "Xi"];
function displayParticipants() {
let parentElementChatSection = document.getElementById("participantButtons");
let participants = participantsArray;
for (let participant of participants) {
participantsElement(participant, parentElementChatSection);
}
}
function participantsElement(participant, parentElement) {
let participantDiv1 = createHTMLElement(parentElement, "div", "participantDiv");
let button = createButtonElement(participantDiv1, participant, "participantButton", (function(variable) {
return function() {
handleParticipant(variable);
};
})(participant));
}
function createButtonElement(parentElement, text, className,
functionToExecute) {
let element = document.createElement("input");
element.type = "button";
element.value = text;
element.className = className + "Hidden";
element.id = text + "Hidden";
parentElement.appendChild(element);
let label = document.createElement("label");
label.htmlFor = element.id;
label.className = className;
label.addEventListener('click', functionToExecute);
parentElement.appendChild(label);
element.style.display = "none";
let textElement = createTextElement(label, text, className + "Text");
return [element, label, textElement];
}
function handleParticipant(participant) {
alert(participant);
}
function createTextElement(parentElement, text, className) {
let element = document.createElement("p");
let elementText = document.createTextNode(text);
element.className = className;
element.appendChild(elementText);
parentElement.appendChild(element);
return element;
}
function createHTMLElement(parentElement, type, className) {
let element = document.createElement(type);
element.className = className;
parentElement.appendChild(element);
return element;
}
displayParticipants();
.participantButtonText {
box-shadow: 0px 5px 10px 1px rgba(18, 140, 126, 0.25);
padding: 0.5em;
margin: 0.5em;
background-color: #128C7E;
color: white;
}
.participantButtonText:hover {
background-color: #075E54;
}
.participantDiv {
position: relative;
float: left;
height: auto;
flex-shrink: 1;
flex-grow: 1;
min-width: 30px;
transition: 0.1s;
transition-property: background-color, color, transform;
text-align: center;
}
#participantButtons {
width: 100%;
clear: both;
display: flex;
flex-direction: row;
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
}
.displayedParticipantButton {
background-color: rgb(172, 117, 0);
}
.displayedParticipantButton:hover {
background-color: rgb(172, 92, 0);
}
<div id="participantButtons">
</div>