首页 > 解决方案 > 如何仅在加载元素后触发事件?

问题描述

我正在创建一个简单的标签系统。

我还添加了删除数组的功能。但是,我遇到了一个问题。每当我启动事件侦听器以删除项目时,我都会收到此错误:Uncaught TypeError: Cannot set property 'onclick' of undefined.

我知道我收到此错误是因为该元素在 DOM 中不可见/未创建。由于标签仅在单击按钮后出现,如何仅在加载标签元素后启动事件?

这是代码:

const tagsInput = document.getElementById('tagsField');
const tagsBtn = document.getElementById('getTags');
const ul = document.getElementById('ul');
let tagsRemover = document.getElementsByClassName('removeTag');
let tagsElemnts = document.getElementsByClassName('tags');
let tagsContainer = [];

let getTags = () => {
	if(tagsInput.value) {
		tagsInput.classList.remove('hasError');
		let tags = tagsInput.value.split(",");
		let pure_tags = tags.map((x) => x.trim());
		tagsContainer = [...pure_tags];
	} else {
		tagsInput.classList.add('hasError');
	}
}

let showTags = () => {
	if(tagsContainer.length > 0) {
		tagsContainer.forEach((element) => {
			let container = document.createElement('LI');
			container.innerHTML = '<span class="removeTag">&#10006;&nbsp;</span>'+element;
			container.className = 'tags';
			ul.appendChild(container);
		});
		tagsContainer = [];
		tagsInput.value = '';
	}
}

tagsInput.addEventListener('input', getTags);
tagsBtn.addEventListener('click', showTags);

// I am doing i < 2 just for debug purpose
for(let i = 0; i < 2; i = i + 1) {
	tagsRemover[i].onclick = () => {
		tagsElemnts[i].style.display = 'none';
	}
}
label {
  font-size: 24px;
  font-family: Roboto;
}
input[type=button] {
  font-size: 18px;
  border: none;
  color: #fff;
  padding: 0.6em 1.5em;
  border-radius: 2em;
  background: #ff4040;
  cursor: pointer;
  outline: none;
  margin-left: 0.5em;
}
input[type=text] {
  font-size: 1.4em;
  padding: 0.4em 0.7em;
  outline: none;
  border: 2px solid #c2c2c2;
  transition: all 150ms ease-in-out;
}
input[type=text]:focus {
  border-color: #0095ff;
}
.tags {
  list-style: none;
  background: #03A9F4;
  color: #fff;
  font-family: Roboto, sans-serif;
  padding: 0.5em 1em;
  border-radius: 10em;
  text-align: center;
  display: inline;
  font-size: 14px;
  margin-left: 0.5em;
}
.removeTag {
  color: #fff;
  display: inline;
  cursor: pointer;
}
.hasError {
  border-color: #ff0023 !important;
}
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Get Tags</title>
</head>
<body>
	<label for="tags">Tags: </label>
	<input type="text" id="tagsField">&nbsp;
	<input type="button" value="Get Tags" id="getTags">
	<br>
	<br>
	<ul id="ul"></ul>
</body>
</html>

标签: javascript

解决方案


添加检查,tagsRemover[i]错误将消失。

当前代码:

tagsRemover[i].onclick = () => {
  tagsElemnts[i].style.display = 'none';
}

改成:

  if (tagsRemover[i]) {
    tagsRemover[i].onclick = () => {
      tagsElemnts[i].style.display = 'none';
    }
  }

下面是工作代码片段:

const tagsInput = document.getElementById('tagsField');
const tagsBtn = document.getElementById('getTags');
const ul = document.getElementById('ul');
let tagsRemover = document.getElementsByClassName('removeTag');
let tagsElemnts = document.getElementsByClassName('tags');
let tagsContainer = [];

let getTags = () => {
  if (tagsInput.value) {
    tagsInput.classList.remove('hasError');
    let tags = tagsInput.value.split(",");
    let pure_tags = tags.map((x) => x.trim());
    tagsContainer = [...pure_tags];
  } else {
    tagsInput.classList.add('hasError');
  }
}

let showTags = () => {
  if (tagsContainer.length > 0) {
    tagsContainer.forEach((element) => {
      let container = document.createElement('LI');
      container.innerHTML = '<span class="removeTag">&#10006;&nbsp;</span>' + element;
      container.className = 'tags';
      ul.appendChild(container);
    });
    tagsContainer = [];
    tagsInput.value = '';
  }
}

tagsInput.addEventListener('input', getTags);
tagsBtn.addEventListener('click', showTags);

// I am doing i < 2 just for debug purpose
for (let i = 0; i < 2; i = i + 1) {
  if (tagsRemover[i]) {
    tagsRemover[i].onclick = () => {
      tagsElemnts[i].style.display = 'none';
    }
  }
}
label {
  font-size: 24px;
  font-family: Roboto;
}

input[type=button] {
  font-size: 18px;
  border: none;
  color: #fff;
  padding: 0.6em 1.5em;
  border-radius: 2em;
  background: #ff4040;
  cursor: pointer;
  outline: none;
  margin-left: 0.5em;
}

input[type=text] {
  font-size: 1.4em;
  padding: 0.4em 0.7em;
  outline: none;
  border: 2px solid #c2c2c2;
  transition: all 150ms ease-in-out;
}

input[type=text]:focus {
  border-color: #0095ff;
}

.tags {
  list-style: none;
  background: #03A9F4;
  color: #fff;
  font-family: Roboto, sans-serif;
  padding: 0.5em 1em;
  border-radius: 10em;
  text-align: center;
  display: inline;
  font-size: 14px;
  margin-left: 0.5em;
}

.removeTag {
  color: #fff;
  display: inline;
  cursor: pointer;
}

.hasError {
  border-color: #ff0023 !important;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Get Tags</title>
</head>

<body>
  <label for="tags">Tags: </label>
  <input type="text" id="tagsField">&nbsp;
  <input type="button" value="Get Tags" id="getTags">
  <br>
  <br>
  <ul id="ul"></ul>
</body>

</html>


推荐阅读