【问题标题】:How do I get this div to show again using JavaScript如何使用 JavaScript 让这个 div 再次显示
【发布时间】:2022-07-07 23:21:03
【问题描述】:

我制作了一个 TODO 应用程序并添加了一个计数器来记录列表中的项目。如果计数器达到零,我已将其设置为重新显示消息“您当前没有任务。使用上面的输入字段开始添加。'

if(count === 0){
  noTasksText.classList.remove('d-none');
}

在控制台中,我打印出 div,它在类列表中不再有 d-none,这是我想要的,但是,在实际的 DOM 中它确实如此。

这是一个完整的例子 - https://codepen.io/tomdurkin/pen/LYdpXKJ?editors=1111

我似乎真的无法解决这个问题。当计数器变为零时,我似乎无法与该 div 交互,但是我可以让控制台日志等在预期时显示。

任何帮助将不胜感激!

const mainInput = document.querySelector('#main-input');
const todoContainer = document.querySelector('#todo-container');
const errorText = document.querySelector('#js-error');
const noTasksText = document.querySelector('.js-no-tasks')

let tasks = [];
let count = 0;

// focus input on load
window.onload = () => {
  mainInput.focus();

  const storedTasks = JSON.parse(localStorage.getItem('tasks'));

  if (storedTasks != null && storedTasks.length > 0) {

    // set count to number of pre-existing items
    count = storedTasks.length

    // hide the 'no tasks' text
    noTasksText.classList.add('d-none');

    // overwrite tasks array with stored tasks
    tasks = storedTasks;

    tasks.forEach(task => {
      // Build the markup
      const markup = `
        <div class="js-single-task single-task border-bottom pt-2 pb-2">
          <div class="row">
            <div class="col d-flex align-items-center js-single-task-name">
              <h5 class="mb-0" data-title="${task}">${task}</h5>
            </div>
            <div class="col d-flex justify-content-end">
              <button class="js-remove-task d-block btn btn-danger">Remove Item</button>
            </div>
          </div>
        </div>`;

      // Append it to the container
      todoContainer.innerHTML += markup;
    });

  } else {
    if (noTasksText.classList.contains('d-none')) {
      noTasksText.classList.remove('d-none');
    }
  }

};

// event listener for 'enter on input' 
mainInput.addEventListener("keydown", e => {

  // if error is showing, hide it!
  if (!errorText.classList.contains('d-none')) {
    errorText.classList.add('d-none');
  }

  if (e.key === "Enter") {

    // Get the value of the input
    let inputValue = mainInput.value;

    if (inputValue) {

      // Build the markup
      const markup = `
        <div class="js-single-task border-bottom pt-2 pb-2">
          <div class="row">
            <div class="col d-flex align-items-center js-single-task-name">
              <h5 class="mb-0" data-title="${inputValue}">${inputValue}</h5>
            </div>
            <div class="col d-flex justify-content-end">
              <button class="js-remove-task d-block btn btn-danger">Remove Item</button>
            </div>
          </div>
        </div>`;

      // hide 'no tasks' text 
      noTasksText.classList.add('d-none');

      // Append it to the container
      todoContainer.innerHTML += markup;

      // Push value to 'tasks' array
      tasks.push(inputValue);

      // Put in localStorage
      textTasks = JSON.stringify(tasks);
      localStorage.setItem("tasks", textTasks);

      // Reset the value of the input field
      mainInput.value = '';

      // add 1 to the count 
      count++

    } else {
      // Some very basic validation
      errorText.classList.remove('d-none');
    }

  }
});

// remove task

todoContainer.addEventListener('click', (e) => {

  // Find the button in the row that needs removing (bubbling)
  const buttonIsDelete = e.target.classList.contains('js-remove-task');

  if (buttonIsDelete) {

    // Remove the HTML from the screen
    e.target.closest('.js-single-task').remove();

    // Grab the name of the single task
    let taskName = e.target.closest('.js-single-task').querySelector('.js-single-task-name h5').getAttribute('data-title');

    // filter out the selected word
    tasks = tasks.filter(item => item != taskName);

    textTasks = JSON.stringify(tasks);
    localStorage.setItem("tasks", textTasks);

    // update counter 
    count--

    // check if counter is zero and re-show 'no tasks' text if true
    if (count === 0) {
      noTasksText.classList.remove('d-none');
      console.log(noTasksText);
    }

  }

});
body {
  background: #e1e1e1;
}
<div class="container">

  <div class="row d-flex justify-content-center mt-5">
    <div class="col-10 col-lg-6">
      <div class="card p-3">
        <h2>To dos</h2>
        <p>
          Use this app to keep a list of things you need to do
        </p>
        <input class="form-control" id="main-input" type="text" placeholder="Type your todo and hit enter..." class="w-100" />
        <small id="js-error" class="text-danger d-none">
        Please type a value and press enter
      </small>
        <hr />
        <h4 class="mb-5">Your 'To dos'</h4>
        <div id="todo-container">
          <!-- todos append in here -->
          <div class="js-no-tasks">
            <small class="d-block w-100 text-center mb-3">
            <i>
              You currently have no tasks. Use the input field above to start adding
            </i>
          </small>
          </div>
        </div>
      </div>
      <!-- /card -->
    </div>
  </div>

</div>

【问题讨论】:

  • 请阅读How to Ask,其中注明。 “如果可以创建一个可以链接到的问题的实时示例(例如,在sqlfiddle.comjsbin.com),那么就这样做 - 但也将代码复制到问题本身中。不是每个人都可以访问外部网站,链接可能会随着时间的推移而中断。使用Stack Snippets 进行内联 JavaScript/HTML/CSS 的现场演示。”
  • 注意,调用remove之前不需要检查类是否存在;如果您调用remove 并且该类不存在,则不会发生错误。
  • 谢谢,我会删除那张支票!
  • 我感觉这是因为querySelector 返回了对非活动元素的引用。你可以试试document.querySelector('.js-no-tasks').classList.remove('d-none') 看看是否可行。但这似乎不对,这就是我不回答的原因:)。
  • 当您使用innerHTML += 处理DOM 时,您丢失了变量noTasksText 的引用。简单的解决方案是在删除按钮处理程序const noTasksText = document.querySelector(".js-no-tasks"); 中声明变量

标签: javascript


【解决方案1】:

您可以执行以下操作,它会起作用(这里innerHTML正在更改DOM,所以我添加了一个额外的功能来重新计算由于innerHTML而更改DOM后的元素):

var mainInput = document.querySelector("#main-input");
var todoContainer = document.querySelector("#todo-container");
var errorText = document.querySelector("#js-error");
var noTasksText = document.querySelector(".js-no-tasks");

let tasks = [];
let count = 0;

function getAllElements() {
  mainInput = document.querySelector("#main-input");
  todoContainer = document.querySelector("#todo-container");
  errorText = document.querySelector("#js-error");
  noTasksText = document.querySelector(".js-no-tasks");
}
// focus input on load
window.onload = () => {
  mainInput.focus();

  var storedTasks = JSON.parse(localStorage.getItem("tasks"));

  if (storedTasks != null && storedTasks.length > 0) {
    // set count to number of pre-existing items
    count = storedTasks.length;

    // hide the 'no tasks' text
    noTasksText.classList.add("d-none");

    // overwrite tasks array with stored tasks
    tasks = storedTasks;

    tasks.forEach((task) => {
      // Build the markup
      const markup = `
        <div class="js-single-task single-task border-bottom pt-2 pb-2">
          <div class="row">
            <div class="col d-flex align-items-center js-single-task-name">
              <h5 class="mb-0" data-title="${task}">${task}</h5>
            </div>
            <div class="col d-flex justify-content-end">
              <button class="js-remove-task d-block btn btn-danger">Remove Item</button>
            </div>
          </div>
        </div>`;

      // Append it to the container
      todoContainer.innerHTML += markup;
      getAllElements();
    });
  } else {
    if (noTasksText.classList.contains("d-none")) {
      noTasksText.classList.remove("d-none");
    }
  }
};

// event listener for 'enter on input'
mainInput.addEventListener("keydown", (e) => {
  // if error is showing, hide it!
  if (!errorText.classList.contains("d-none")) {
    errorText.classList.add("d-none");
  }

  if (e.key === "Enter") {
    // Get the value of the input
    let inputValue = mainInput.value;

    if (inputValue) {
      // Build the markup
      const markup = `
        <div class="js-single-task border-bottom pt-2 pb-2">
          <div class="row">
            <div class="col d-flex align-items-center js-single-task-name">
              <h5 class="mb-0" data-title="${inputValue}">${inputValue}</h5>
            </div>
            <div class="col d-flex justify-content-end">
              <button class="js-remove-task d-block btn btn-danger">Remove Item</button>
            </div>
          </div>
        </div>`;

      // hide 'no tasks' text
      noTasksText.classList.add("d-none");

      // Append it to the container
      todoContainer.innerHTML += markup;
      getAllElements();

      // Push value to 'tasks' array
      tasks.push(inputValue);

      // Put in localStorage
      textTasks = JSON.stringify(tasks);
      localStorage.setItem("tasks", textTasks);

      // Reset the value of the input field
      mainInput.value = "";

      // add 1 to the count
      count++;
    } else {
      // Some very basic validation
      errorText.classList.remove("d-none");
    }
  }
});

// remove task

todoContainer.addEventListener("click", (e) => {
  // Find the button in the row that needs removing (bubbling)
  const buttonIsDelete = e.target.classList.contains("js-remove-task");

  if (buttonIsDelete) {
    // Remove the HTML from the screen
    e.target.closest(".js-single-task").remove();

    // Grab the name of the single task
    let taskName = e.target
      .closest(".js-single-task")
      .querySelector(".js-single-task-name h5")
      .getAttribute("data-title");

    // filter out the selected word
    tasks = tasks.filter((item) => item != taskName);

    textTasks = JSON.stringify(tasks);
    localStorage.setItem("tasks", textTasks);

    // update counter
    count--;

    // check if counter is zero and re-show 'no tasks' text if true
    if (count === 0) {
      noTasksText.classList.remove("d-none");
      console.log(noTasksText);
    }
  }
});
body {
  background: #e1e1e1;
}
<div class="container">

  <div class="row d-flex justify-content-center mt-5">
    <div class="col-10 col-lg-6">
      <div class="card p-3">
        <h2>To dos</h2>
        <p>
          Use this app to keep a list of things you need to do
        </p>
        <input class="form-control" id="main-input" type="text" placeholder="Type your todo and hit enter..." class="w-100" />
        <small id="js-error" class="text-danger d-none">
        Please type a value and press enter
      </small>
        <hr />
        <h4 class="mb-5">Your 'To dos'</h4>
        <div id="todo-container">
          <!-- todos append in here -->
          <div class="js-no-tasks">
            <small class="d-block w-100 text-center mb-3">
            <i>
              You currently have no tasks. Use the input field above to start adding
            </i>
          </small>
          </div>
        </div>
      </div>
      <!-- /card -->
    </div>
  </div>

</div>

【讨论】:

    【解决方案2】:

    在使用+= innerHTML 设置innerHTML 时,节点noTasksText 会丢失,因为浏览器会处理整个新集合innerHTML 并创建新对象。您可以在此之后再次检索noTasksText,或使用todoContainer.appendChild 附加节点。我叉了你的笔,用后一种方法解决了。

    https://codepen.io/aghosey/pen/wvmGwWd

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多