为什么只有 keydown 起作用,而 keyup 或 keypress 不起作用?

Why does only keydown work, and not keyup or keypress?

我有以下将待办事项添加到待办事项应用程序的代码:

HTML:

<div id="root">
  <form class="todoForm">
    <input class="input" placeholder="What do you need to do?" />
  </form>
  <div class="todos"></div>
  <div class="footer">
    <button class="All">All</button>
    <button class="All">Active</button>
    <button class="All">Completed</button>
  </div>
</div>

CSS:

.todoForm {
  margin-bottom: 20px;
}

.todos {
  margin-bottom: 20px;
}

.todo {
  margin-bottom: 10px;
}

.todoAndCheckBox {
  display: flex
}

.checkBox {
  border-radius: 50%;
  outline: green;
}


JS:

class displayTodos {
  constructor(root) {
    this.root = root;
    this.input = this.root.querySelector('.input');
    this.form = this.root.querySelector('.todoForm');
    // why does it work with keydown but not keyup
    this.form.addEventListener('keydown', this.submitForm);
    this.todos = this.root.querySelector('.todos');
    this.state = {
      todos: [
        {
          id: Math.random * 10000,
          text: 'Pie'
        },
        {
          id: Math.random * 10000,
          text: 'Soy milk'
        }
      ]
    }
    this.display();
  }
  
  submitForm = (e) => {
    if(e.key === 'Enter') {
      e.preventDefault();
      const typed = this.input.value;
      const newTodo = {
        id: Math.random * 10000,
        text: typed
      }
      
      const newTodos = [...this.state.todos, newTodo];
      
      this.state.todos = newTodos;
      this.display();
      this.input.value = ''
    }
  }
  
  display = () => {
    while(this.todos.firstChild) {
      this.todos.removeChild(this.todos.firstChild)
    }
    this.state.todos.forEach(todo => {
      const todoAndCheckBox = document.createElement('div');
      const todoDiv = document.createElement('div');
      todoAndCheckBox.classList.add('todoAndCheckBox');
      todoDiv.innerText = todo.text;
      const checkBox = document.createElement('input');
      checkBox.setAttribute('type', 'checkbox');
      checkBox.classList.add('checkBox');
      this.todos.appendChild(todoAndCheckBox);
      todoAndCheckBox.appendChild(checkBox);
      todoAndCheckBox.appendChild(todoDiv);
      
      todoAndCheckBox.classList.add('todo')
    })
  }
  
}

const root = document.querySelector('#root');
const instance = new displayTodos(root);

在这一行:

this.form.addEventListener('keydown', this.submitForm);

我注意到,如果我将 keydown 更改为 keyupkeypress,当我按回车键时,即使我有 e.preventDefault,整个页面也会刷新。 我的问题是:

  1. 为什么 page/form 用 e.preventDefault 刷新?
  2. 为什么只有 keydown 有效(意味着它阻止表单刷新),但 keyupkeypress 无效?

提交表单事件已经由 keydown 触发,如果您在 keyup 上使用 e.preventDefault,则为时已晚。 您应该更改代码以绑定到 keydown 和 keyup。在 keydown 函数上,您可以调用 e.preventDefault(),在 keyup 函数上,您可以执行其他逻辑。

交替:

您可以使用以下代码完全禁用表单提交:

<form onsubmit="return false;">

然后在您确实希望它发生时手动触发表单提交:

document.forms[0].submit();

以上假设您只有一种形式 - 如果您现在或将来有多个选择器,您可能想使用 css 选择器:

document.querySelector("#formid").submit();

另请注意,提交按钮将不再有效,因此您需要将事件连接到它们的点击事件以通过相同的代码提交。