在按钮上使用 addEventListener() 添加 DOM 元素时的奇怪行为
Strange behavior while adding DOM element using addEventListener() on a button
我正在尝试在用户单击按钮时创建包含用户信息的项目卡片。当用户单击新项目按钮时,会弹出一个模态表单,其中包含用户信息和一个创建按钮。每当用户单击创建按钮时,程序应该添加一个新的项目卡。为此,我向 Add new project
按钮和 Create
按钮添加了一个点击事件侦听器。我将创建事件监听器嵌套在添加新项目事件监听器中。
这是事件侦听器。
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
});
问题是当我创建第一张卡片时它工作正常。但是第二次,它创建了两张卡片,第三次创建了三张卡片,依此类推。
这是完整代码的 JSFiddle link。
我已经编辑了你的代码,这应该是你想要的:
const logoutBtn = document.querySelector("#logout");
const addTileBtn = document.querySelector("#add-tile");
const cardsGrid = document.querySelector(".cards-grid");
const modal = document.querySelector(".modal");
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
titleField.value = "";
descriptionField.value = "";
});
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
:root {
--main-red: #be3144;
--main-white: #f0f0f0;
--main-gray: #303841;
--main-blue: #45567d;
--main-blue3: #1c262f;
--main-blue2: #27333d;
--main-blue1: #2e3d49;
--main-light-blue: #02b3e4;
--main-black: #000000;
--main-light-black: #3a3d40;
--main-dark-black: #181719;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
img {
display: block;
max-width: 100%;
height: auto;
}
body {
font-family: "Poppins", sans-serif;
font-size: 1.8rem;
font-weight: 400;
line-height: 1.4;
color: var(--main-white);
}
h1,
h2 {
font-family: "Raleway", sans-serif;
font-weight: 700;
text-align: center;
}
h1 {
font-size: 3.5rem;
}
h2 {
font-size: 2rem;
color: var(--main-blue);
display: block;
}
p {
font-size: 1.8rem;
font-weight: 200;
font-style: italic;
color: var(--main-white);
}
a {
text-decoration: none;
text-align: center;
display: block;
}
.main {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100vh;
background-color: var(--main-white);
}
.box {
border: none;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%), 0 8px 16px rgb(0 0 0 / 10%);
border-radius: 8px;
background-color: #fff;
}
.box__fields {
padding: 20px;
}
.box-field {
margin-bottom: 20px;
display: flex;
justify-content: center;
}
.icon {
position: absolute;
padding: 10px;
color: gray;
min-width: 50px;
text-align: center;
font-size: 20px;
top: 50%;
transform: translateY(-50%);
}
input,
textarea {
font-size: 17px;
padding: 14px 16px;
width: 300px;
cursor: text;
border: 1px solid var(--main-gray);
border-radius: 6px;
outline: none;
padding-left: 45px;
}
.box-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 48px;
padding: 0 16px;
}
.app,
.main-content {
height: 100%;
}
.title-area {
background-color: var(--main-blue3);
width: 100%;
font-size: 18px;
min-height: 60px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
position: fixed;
top: 0;
left: 0;
}
.title-area__item {
padding: 10px 30px;
}
.logout-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 30px;
padding: 0 16px;
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.logout-btn:hover {
background-color: #029be4;
}
.content-area {
margin-top: 60px;
width: 100%;
height: 100%;
overflow: auto;
background-color: var(--main-blue);
}
.cards-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 50px;
margin-bottom: 3rem;
padding: 5rem 3rem;
}
.cards-grid__tile {
background-color: var(--main-blue2);
max-width: 200px;
padding: 30px;
text-align: center;
font-size: 1.2rem;
}
.add-tile-btn {
border: none;
border-radius: 6px;
font-size: 15px;
line-height: 48px;
padding: 0 10px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.modal {
display: none;
width: 350px;
font-size: 1.2rem;
position: relative;
top: 10%;
left: 50%;
transform: translateX(-50%);
overflow: visible;
}
.box {
background-color: var(--main-blue1);
opacity: 0.95;
}
.box-field {
flex-direction: column;
}
input,
textarea {
padding: 5px 10px;
resize: none;
}
.wrapper {
position: relative;
text-align: center;
}
.create-btn {
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.close {
cursor: pointer;
position: absolute;
top: 20px;
left: 290px;
}
#modal-form {
position: absolute;
}
.icon {
color: var(--main-blue3);
}
<div class="app">
<div class="nav-wrapper">
<nav id="nav" class="nav"></nav>
</div>
<div class="main-content">
<div class="title-area">
<div class="title-area__item">Menu</div>
<div class="title-area__item">Boards</div>
<div class="title-area__item">
<button id="logout" class="logout-btn btn">
Logout
</button>
</div>
</div>
<div class="content-area">
<div class="modal">
<form id="modal-form" class="box">
<a id="close" class="close">
<i class="fa fa-times icon">close</i>
</a>
<div class="box__fields">
<div class="box-field">
<label for="title"> Title </label>
<input
id="title"
type="text"
name="title"
required
autofocus
/>
</div>
<div class="box-field">
<label for="description">
Description
</label>
<textarea
id="description"
name="title"
rows="6"
cols="40"
></textarea>
</div>
<div class="box-field">
<div class="wrapper">
<button
id="create"
class="create-btn box-btn btn"
>
Create
</button>
</div>
</div>
</div>
</form>
</div>
<div class="cards-grid">
<div class="cards-grid__tile">
<button id="add-tile" class="add-tile-btn btn">
+ Add new project
</button>
</div>
</div>
</div>
</div>
</div>
我正在尝试在用户单击按钮时创建包含用户信息的项目卡片。当用户单击新项目按钮时,会弹出一个模态表单,其中包含用户信息和一个创建按钮。每当用户单击创建按钮时,程序应该添加一个新的项目卡。为此,我向 Add new project
按钮和 Create
按钮添加了一个点击事件侦听器。我将创建事件监听器嵌套在添加新项目事件监听器中。
这是事件侦听器。
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
});
问题是当我创建第一张卡片时它工作正常。但是第二次,它创建了两张卡片,第三次创建了三张卡片,依此类推。
这是完整代码的 JSFiddle link。
我已经编辑了你的代码,这应该是你想要的:
const logoutBtn = document.querySelector("#logout");
const addTileBtn = document.querySelector("#add-tile");
const cardsGrid = document.querySelector(".cards-grid");
const modal = document.querySelector(".modal");
const titleField = document.querySelector("#title");
const descriptionField = document.querySelector("#description");
const create = document.querySelector("#create");
const close = document.querySelector("#close");
addTileBtn.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "block";
titleField.value = "";
descriptionField.value = "";
});
create.addEventListener("click", (e) => {
e.preventDefault();
title = titleField.value;
description = descriptionField.value;
function createProjectTile() {
const projectTile = document.createElement("div");
projectTile.classList.add("cards-grid__tile");
projectTile.textContent = title;
console.log(title, description);
return projectTile;
}
cardsGrid.appendChild(createProjectTile());
modal.style.display = "none";
});
close.addEventListener("click", (e) => {
e.preventDefault();
modal.style.display = "none";
});
:root {
--main-red: #be3144;
--main-white: #f0f0f0;
--main-gray: #303841;
--main-blue: #45567d;
--main-blue3: #1c262f;
--main-blue2: #27333d;
--main-blue1: #2e3d49;
--main-light-blue: #02b3e4;
--main-black: #000000;
--main-light-black: #3a3d40;
--main-dark-black: #181719;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
img {
display: block;
max-width: 100%;
height: auto;
}
body {
font-family: "Poppins", sans-serif;
font-size: 1.8rem;
font-weight: 400;
line-height: 1.4;
color: var(--main-white);
}
h1,
h2 {
font-family: "Raleway", sans-serif;
font-weight: 700;
text-align: center;
}
h1 {
font-size: 3.5rem;
}
h2 {
font-size: 2rem;
color: var(--main-blue);
display: block;
}
p {
font-size: 1.8rem;
font-weight: 200;
font-style: italic;
color: var(--main-white);
}
a {
text-decoration: none;
text-align: center;
display: block;
}
.main {
display: flex;
flex-direction: row;
justify-content: space-between;
height: 100vh;
background-color: var(--main-white);
}
.box {
border: none;
box-shadow: 0 2px 4px rgb(0 0 0 / 10%), 0 8px 16px rgb(0 0 0 / 10%);
border-radius: 8px;
background-color: #fff;
}
.box__fields {
padding: 20px;
}
.box-field {
margin-bottom: 20px;
display: flex;
justify-content: center;
}
.icon {
position: absolute;
padding: 10px;
color: gray;
min-width: 50px;
text-align: center;
font-size: 20px;
top: 50%;
transform: translateY(-50%);
}
input,
textarea {
font-size: 17px;
padding: 14px 16px;
width: 300px;
cursor: text;
border: 1px solid var(--main-gray);
border-radius: 6px;
outline: none;
padding-left: 45px;
}
.box-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 48px;
padding: 0 16px;
}
.app,
.main-content {
height: 100%;
}
.title-area {
background-color: var(--main-blue3);
width: 100%;
font-size: 18px;
min-height: 60px;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
position: fixed;
top: 0;
left: 0;
}
.title-area__item {
padding: 10px 30px;
}
.logout-btn {
border: none;
border-radius: 6px;
font-size: 20px;
line-height: 30px;
padding: 0 16px;
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.logout-btn:hover {
background-color: #029be4;
}
.content-area {
margin-top: 60px;
width: 100%;
height: 100%;
overflow: auto;
background-color: var(--main-blue);
}
.cards-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
grid-gap: 50px;
margin-bottom: 3rem;
padding: 5rem 3rem;
}
.cards-grid__tile {
background-color: var(--main-blue2);
max-width: 200px;
padding: 30px;
text-align: center;
font-size: 1.2rem;
}
.add-tile-btn {
border: none;
border-radius: 6px;
font-size: 15px;
line-height: 48px;
padding: 0 10px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.modal {
display: none;
width: 350px;
font-size: 1.2rem;
position: relative;
top: 10%;
left: 50%;
transform: translateX(-50%);
overflow: visible;
}
.box {
background-color: var(--main-blue1);
opacity: 0.95;
}
.box-field {
flex-direction: column;
}
input,
textarea {
padding: 5px 10px;
resize: none;
}
.wrapper {
position: relative;
text-align: center;
}
.create-btn {
width: 100px;
cursor: pointer;
color: #fff;
background-color: var(--main-light-blue);
}
.close {
cursor: pointer;
position: absolute;
top: 20px;
left: 290px;
}
#modal-form {
position: absolute;
}
.icon {
color: var(--main-blue3);
}
<div class="app">
<div class="nav-wrapper">
<nav id="nav" class="nav"></nav>
</div>
<div class="main-content">
<div class="title-area">
<div class="title-area__item">Menu</div>
<div class="title-area__item">Boards</div>
<div class="title-area__item">
<button id="logout" class="logout-btn btn">
Logout
</button>
</div>
</div>
<div class="content-area">
<div class="modal">
<form id="modal-form" class="box">
<a id="close" class="close">
<i class="fa fa-times icon">close</i>
</a>
<div class="box__fields">
<div class="box-field">
<label for="title"> Title </label>
<input
id="title"
type="text"
name="title"
required
autofocus
/>
</div>
<div class="box-field">
<label for="description">
Description
</label>
<textarea
id="description"
name="title"
rows="6"
cols="40"
></textarea>
</div>
<div class="box-field">
<div class="wrapper">
<button
id="create"
class="create-btn box-btn btn"
>
Create
</button>
</div>
</div>
</div>
</form>
</div>
<div class="cards-grid">
<div class="cards-grid__tile">
<button id="add-tile" class="add-tile-btn btn">
+ Add new project
</button>
</div>
</div>
</div>
</div>
</div>