代码之家  ›  专栏  ›  技术社区  ›  Axel

如何仅在加载元素后激发事件?

  •  2
  • Axel  · 技术社区  · 6 年前

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

    我还添加了移除数组的功能。但是,我遇到了一个问题。每当我启动事件侦听器删除该项时,都会收到以下错误: 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>
    1 回复  |  直到 6 年前
        1
  •  2
  •   Vikasdeep Singh    6 年前

    在处添加支票 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>