ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 다음 js 코드에 이벤트 리스너가 추가되지 않음
    카테고리 없음 2020. 8. 18. 03:47

    질문

    자바스크립트를 사용하여 동적으로 작업을 생성하는 할일 앱을 만들고 있습니다. [(샘플 출력)]추가 button을 클릭 할 때마다 js에서 다음과 같은 동등한 html을 생성합니다.

    <div class="row datasection">
      <div class="todo">
        <div class="databox col s6 offset-s1 waves-effect">
          <p class="checkglyph1 checkglyph2">Task no 1</p>
          <a>
            <i class="material-icons checkglyph checkglyph1 checkglyph2 glyphcolor">check</i>
          </a>
        </div>
      </div>
    </div>

    이제 내가 원하는 것은 생성 된 작업에서 이벤트를 클릭 할 때마다 노란색이되어야한다는 것입니다. 하지만 하나의 작업이 생성 된 경우에만 잘 작동합니다. 여러 개의 작업이 있으면 마지막 작업은 잘 작동하지만 첫 번째 작업의 actionlistener는 작동하지 않는 것 같습니다.

    var glyph= document.querySelectorAll(".glyphcolor");
    
    for (var i = 0; i < glyph.length; i++) {
        glyph[i].addEventListener('click', function(event) {
            this.classList.toggle("checkglyph1");
        });
    }

    실제 snippet

    //declaration
        var calendardata = document.getElementById('date1');
        var addbutton = document.querySelector('.addbutton');
        var todo = document.querySelector('.todo');
        addbutton.addEventListener('click', function() {
    
    /* body to return the html */
    
          if (data.value) {
            var newdiv = document.createElement("div"); // Create a <button> element
            newdiv.classList.add("databox", "col", "s6", "waves-effect");
            //console.log(newdiv);
            todo.appendChild(newdiv);
            //console.log(newdiv.parentNode);
            var newpar = document.createElement("p");
            newpar.classList.add("checkglyph1", "checkglyph2");
            var node = document.createTextNode(data.value + "." + "      " + 
            calendardata.value);
            var newa = document.createElement("a");
            newdiv.appendChild(newa)
            var newglyph = document.createElement("i");
            newglyph.classList.add("material-icons", "checkglyph", "checkglyph1", 
            "checkglyph2", "glyphcolor");
            var node1 = document.createTextNode("check");
            newa.appendChild(newglyph);
            newglyph.append(node1);
            newpar.appendChild(node);
            newdiv.appendChild(newpar);
            data.value = "";
            calendardata.value = "";
            created = true;
          //  console.log("before glyh created");
    
            //code to perform action on the click of the tick symbol
    
            var glyph = document.querySelectorAll(".glyphcolor");
            var par = document.getElementsByClassName('checkglyph2');
            for (var i = 0; i < glyph.length; i++) {
        //console.log("Inside the loop");
        glyph[i].addEventListener('click', function.bind(event) {
            this.classList.toggle("checkglyph1");
            //console.log('Inside the click');
            //console.log(i);
        });
    
    
    }   
    
          }
        })

    답변1

    코드의 문제점은 ".addbutton"을 클릭 할 때마다 DOM의 모든 ".glyphcolor"요소를 살펴보고 새로운 onclick 이벤트 리스너를 추가한다는 것입니다. 마지막으로 생성 된 것이 작동하지만 나머지는 반복되는 여러 이벤트 리스너를 갖게됩니다 (예, 가능합니다). 따라서 "checkglyph1"class를 토글하라는 두 개의 이벤트가있는 요소를 클릭하면 두 번 수행됩니다. 물론 전혀 변하지 않을 것입니다. 페이지의 모든 홀수 요소가 작동해야하고 (홀수 시간으로 class를 토글 할 것임) 짝수 요소는 작동하지 않아야하기 때문에 이런 일이 발생하는 것을 쉽게 볼 수 있습니다.

    이는 페이지에서 생성 할 때 요소에 직접 이벤트 리스너를 추가하여 수정할 수 있습니다. 아래 코드는 제대로 작동해야합니다.

    //declaration
    var calendardata = document.getElementById('date1');
    var addbutton = document.querySelector('.addbutton');
    var todo = document.querySelector('.todo');
    
    addbutton.addEventListener('click', function() {
      if (data.value) {
        var newdiv = document.createElement("div"); // Create a <button> element
        newdiv.classList.add("databox", "col", "s6", "waves-effect");
        //console.log(newdiv);
        todo.appendChild(newdiv);
        //console.log(newdiv.parentNode);
        var newpar = document.createElement("p");
        newpar.classList.add("checkglyph1", "checkglyph2");
        var node = document.createTextNode(data.value + "." + "      " + 
        calendardata.value);
        var newa = document.createElement("a");
        newdiv.appendChild(newa)
        var newglyph = document.createElement("i");
        newglyph.classList.add("material-icons", "checkglyph", "checkglyph1", 
        "checkglyph2", "glyphcolor");
        var node1 = document.createTextNode("check");
        newa.appendChild(newglyph);
        newglyph.append(node1);
        newpar.appendChild(node);
        newdiv.appendChild(newpar);
        data.value = "";
        calendardata.value = "";
        created = true;
    
        newglyph.addEventListener('click', function(event) {
            event.preventDefault(); // Just to prevent non desired effects of click
    
            newglyph.classList.toggle('checkglyph1');
        }
       }
     }

    그리고 약간의 설명이 있습니다. 실제 코드에 "바인딩"이 필요하지 않습니다.

    glyph[i].addEventListener('click', function.bind(event) { // just type function(event)
       this.classList.toggle('checkglyph1');...


    답변2

    다른 작업이 생성 될 때 노드 컬렉션에서 수집되지 않으므로 이벤트 리스너가 없습니다. 대신 container에 이벤트 리스너를 추가하고 클릭 한 항목을 변경하면됩니다.

    document.querySelector('ul').addEventListener('click', changeClass);
    document.querySelector('#button').addEventListener('click', addLi);
    
    function changeClass(e){
      e.target.closest('li').classList.toggle('checkglyph1');
    }
    
    function addLi(e){
      const new_li = document.createElement('li');
      new_li.textContent = document.querySelectorAll('li').length + 1;
      new_li.classList.add('checkglyph1');
      document.querySelector('ul').appendChild(new_li);
    }
    li:not(.checkglyph1) {
      background: #f00;
    }
    <button id="button">Add li</button>
    <ul>
      <li class="checkglyph1">1</li>
      <li class="checkglyph1">2</li>
      <li class="checkglyph1 red">3</li>
      <li class="checkglyph1">4</li>
      <li class="checkglyph1">5</li>
      <li class="checkglyph1">6</li>
      <li class="checkglyph1">7</li>
      <li class="checkglyph1">8</li>
      <li class="checkglyph1">9</li>
      <li class="checkglyph1">10</li>
    </ul>



     

     

     

     

    출처 : https://stackoverflow.com/questions/48350115/eventlisteners-not-being-added-in-the-following-js-code

    댓글

Designed by Tistory.