【问题标题】:Click event only works on the second click点击事件仅适用于第二次点击
【发布时间】:2022-01-24 02:35:47
【问题描述】:

希望你们一切都好,好吧..

我在做一个To Do List,我的代码有问题,这几天我一直在尝试解决,没有得到有效的结果..

如果你们和我一起测试sn-p,我敢肯定,那会更多 清晰易懂。

当我点击某个列表元素时,我的 javascript 应该更改或添加 className,并添加一个类调用 'selected'

因为,当我单击删除按钮时,他们将删除列表中具有“已选择”类列表的所有元素。 (如您在代码中所见)

但是 className a 没有被添加到 first click 中的标签

  • 中,如果我 click /p>
  • 元素再来一次

    我简化了我的代码,只是为了显示真正的问题:

    jsfiddle 链接:https://jsfiddle.net/myqrzcs2/

    const textoTarefa = document.getElementById('texto-tarefa');
    const criarTarefa = document.getElementById('criar-tarefa');
    const listaTarefas = document.getElementById('lista-tarefas');
    criarTarefa.onclick = function click() {
      const lista = document.createElement('li');
      lista.className = 'lista';
      lista.id = 'lista';
      lista.tabIndex = '0';
      lista.innerHTML = textoTarefa.value;
      listaTarefas.appendChild(lista);
      document.body.appendChild(listaTarefas);
      textoTarefa.value = '';
    };
    const completedLine = document.querySelector('ol');
    
    function umClick(event) {
      if (event.target.tagName === 'LI') {
        const listas = document.querySelectorAll('.lista');
        listas.forEach((i) => {
          i.addEventListener('click', function semNomeDois() {
            listas.forEach((j) => j.classList.remove('selected'));
            this.classList.add('selected');
          });
        });
      }
    }
    completedLine.addEventListener('click', umClick);
    
    function removeSelected() {
      // teste
      const listaSelected = document.querySelectorAll('.selected');
      for (let i = 0; i < listaSelected.length; i += 1) {
        listaSelected[i].remove();
      }
    }
    .lista:focus {
      background: red;
    }
    <!DOCTYPE html>
    <html>
    
    <head>
      <link rel='stylesheet' href='style.css'>
    </head>
    
    <body>
      <header>
        <h1>My List</h1>
      </header>
      <input id='texto-tarefa' type="text" />
      <button id='criar-tarefa' type="submit" onClick='click()'>Add</button>
      <ol id='lista-tarefas'>
      </ol>
      <button id='remover-selecionado' type="submit" onClick='removeSelected()'>Remove Selected (Only One)</button>
      <script src="script.js"></script>
    </body>
    
    </html>

    但是我怎样才能让类被添加,只是在第一次点击,而不是在第二次?


  • 【问题讨论】:

    • 不太清楚你在问什么。
    • 很抱歉,你是对的.. 问题是当我点击元素
    • 以添加“选定”类时,不起作用,只是在我第二次点击,它是添加的类..我不知道为什么..
  • 欢迎来到 StackOverflow。请澄清您的问题,以使其易于理解和回答。另外,您能否尝试在多个浏览器上运行您的代码?并确认问题是浏览器特定问题还是一般问题。
  • 好的,我现在会尝试清除更多,感谢您的反馈,并将在不同的浏览器中尝试,只需要几分钟来修复和测试。但是如果尝试使用我的列表,添加和删除它,他们会明白,如果我们这样做可能会更清楚。
  • 我测试,问题依旧,我现在编辑。
  • 标签: javascript html css


    【解决方案1】:

    我认为你在编程时走错了路。 以下是我的使用方式,希望对你有所启发。

    const
      textoTarefa  = document.getElementById('texto-tarefa')
    , criarTarefa  = document.getElementById('criar-tarefa')
    , removerSelec = document.getElementById('remover-selecionado')
    , listaTarefas = document.getElementById('lista-tarefas')
      ;
    var li_selected = null
      ;
    textoTarefa.oninput = () =>
      {
      criarTarefa.disabled = (textoTarefa.value.trim().length ===0 )
      }
    criarTarefa.onclick = () =>
      {
      listaTarefas.appendChild( document.createElement('li')).textContent =  textoTarefa.value.trim()
      textoTarefa.value = ''
      textoTarefa.focus()
      criarTarefa.disabled = true
      }
    listaTarefas.onclick = ({target}) =>
      {
      if (!target.matches('li')) return
      if (!!li_selected && li_selected !== target ) li_selected.classList.remove('listaSelect')
      li_selected = target.classList.toggle('listaSelect') ? target : null
      removerSelec.disabled = !li_selected
      }
    removerSelec.onclick = () =>
      {
      listaTarefas.removeChild(li_selected)
      li_selected = null
      removerSelec.disabled = true
      }
    .listaSelect {
      background: #ff0000c4;
      }
    ol#lista-tarefas {
      cursor : pointer
      }
    <input  id='texto-tarefa' type="text" value="">
    <button id='criar-tarefa' disabled>Add</button>
    <button id='remover-selecionado' disabled>Remove Selected</button>
    <ol id='lista-tarefas'></ol>

    【讨论】:

      【解决方案2】:

      您不必要地为列表中的每个项目添加事件侦听器。

      您可以在此处查看更新的小提琴:https://jsfiddle.net/msa9v2nf/

      由于您已经在检查单击了哪个目标元素,因此无需为列表中的每个子项添加单独的侦听器。

      我更新了umClick函数:

      function umClick(event) {
        if (event.target.tagName === 'LI') {
          const listas = document.querySelectorAll('.lista');
          
          listas.forEach((i) => {
            listas.forEach((j) => j.classList.remove('selected'));
            event.target.classList.add('selected');
          });
        }
      }
      

      【讨论】:

        【解决方案3】:

        问题是您调用函数umClick 并调用函数在同一函数umClick 中的click event 中添加.selected

        点击事件completedLine.addEventListener('click', umClick); 发生在i.addEventListener('click', function semNomeDois() 事件之前。这就是为什么您需要第一次点击ol 标签。

        要解决此问题,您有多种选择:

        1. 您可以调用mousedown,而不是在ol 标记上调用click 事件,这发生在click 事件之前。
        2. 在创建时调用li 元素的点击事件,这需要一个新函数。
        3. 根据 Vektor 的回答,您可以删除第一个 click 事件中不必要的 click 事件。

        另外,我在 .selected 类上做了红色突出显示,而不是 :focus,只是为了在选择项目时清楚。

        .selected {
           background: red;
        }
        

        第一个解决方案

        const textoTarefa = document.getElementById('texto-tarefa');
        const criarTarefa = document.getElementById('criar-tarefa');
        const listaTarefas = document.getElementById('lista-tarefas');
        criarTarefa.onclick = function click() {
          const lista = document.createElement('li');
          lista.className = 'lista';
          lista.id = 'lista';
          lista.tabIndex = '0';
          lista.innerHTML = textoTarefa.value;
          listaTarefas.appendChild(lista);
          document.body.appendChild(listaTarefas);
          textoTarefa.value = '';
        };
        const completedLine = document.querySelector('ol');
        
        function umClick(event) {
          if (event.target.tagName === 'LI') {
            const listas = document.querySelectorAll('.lista');
            listas.forEach((i) => {
              i.addEventListener('click', function semNomeDois() {
                listas.forEach((j) =>{
                  if(j != event.target)
                    j.classList.remove('selected');
                });
                this.classList.add('selected');
              });
            });
          }
        }
        completedLine.addEventListener('mousedown', umClick);
        
        function removeSelected() {
          // teste
          const listaSelected = document.querySelectorAll('.selected');
          for (let i = 0; i < listaSelected.length; i += 1) {
            listaSelected[i].remove();
          }
        }
        .selected {
          background: red;
        }
        <!DOCTYPE html>
        <html>
        
        <head>
          <link rel='stylesheet' href='style.css'>
        </head>
        
        <body>
          <header>
            <h1>My List</h1>
          </header>
          <input id='texto-tarefa' type="text" />
          <button id='criar-tarefa' type="submit" onClick='click()'>Add</button>
          <ol id='lista-tarefas'>
          </ol>
          <button id='remover-selecionado' type="submit" onClick='removeSelected()'>Remove Selected (Only One)</button>
          <script src="script.js"></script>
        </body>
        
        </html>

        第二种解决方案

        const textoTarefa = document.getElementById('texto-tarefa');
        const criarTarefa = document.getElementById('criar-tarefa');
        const listaTarefas = document.getElementById('lista-tarefas');
        criarTarefa.onclick = function click() {
          const lista = document.createElement('li');
          lista.className = 'lista';
          lista.id = 'lista';
          lista.tabIndex = '0';
          lista.innerHTML = textoTarefa.value;
          listaTarefas.appendChild(lista);
          lista.addEventListener('click',function(){
            itemClick(this);
          });
          document.body.appendChild(listaTarefas);
          textoTarefa.value = '';
        };
        
        function itemClick(item) {
            const listas = document.querySelectorAll('.lista');
            listas.forEach((j) =>j.classList.remove('selected'));
           item.classList.add('selected');
        }
        
        function removeSelected() {
          // teste
          const listaSelected = document.querySelectorAll('.selected');
          for (let i = 0; i < listaSelected.length; i += 1) {
            listaSelected[i].remove();
          }
        }
        .selected {
          background: red;
        }
        <!DOCTYPE html>
        <html>
        
        <head>
          <link rel='stylesheet' href='style.css'>
        </head>
        
        <body>
          <header>
            <h1>My List</h1>
          </header>
          <input id='texto-tarefa' type="text" />
          <button id='criar-tarefa' type="submit" onClick='click()'>Add</button>
          <ol id='lista-tarefas'>
          </ol>
          <button id='remover-selecionado' type="submit" onClick='removeSelected()'>Remove Selected (Only One)</button>
          <script src="script.js"></script>
        </body>
        
        </html>

        【讨论】:

        • 谢谢你,天哪,它有效。我会花点时间研究你的代码,不要再犯这个错误,非常感谢。
        • 我已经编辑了答案,以明确解决问题的原因。
        • 这么多的代码,这么少的事……
        • @MisterJojo StackOverflow 不是为解释代码制作的吗?我只是想详细解释一下:)
        • 这很好,但它也适用于代码审查
        【解决方案4】:

        我不完全理解你的问题,但是, 如果要在选择项目时添加样式,只需将样式添加到

        .selected
        

        如果你想获得焦点,并在没有焦点时移除类,你可以添加一个事件监听器来控制它。

        【讨论】:

        • 发生了什么,当我单击元素
        • 添加“已选择”类时,一开始不起作用,只是在我第二次单击时,添加的类..我不知道为什么..
        猜你喜欢
        相关资源
        最近更新 更多
        热门标签