如何在点击处理程序中获取正确的项目
How do I get the correct item in a clickhandler
我有以下代码:
HTML:
<div id="root">
<form class="todoForm">
<input class="input" placeholder="What's gotta be done'?" />
</form>
<div class="todos"></div>
<div class="footer">
<button class="All">All</button>
<button class="Active">Active</button>
<button class="Completed">Completed</button>
<button class="Clear">Clear</button>
</div>
</div>
CSS:
.todoForm {
margin-bottom: 20px;
}
.todos {
margin-bottom: 20px;
}
.todo {
margin-bottom: 10px;
}
.todoAndCheckBox {
display: flex;
font-weight: bold;
}
.checkBox {
border-radius: 50%;
outline: green;
}
.crossOut {
font-weight: normal;
text-decoration: line-through
}
JS:
const COMPLETED = 'completed';
const ACTIVE = 'active';
const ALL = 'all';
class displayTodos {
constructor(root) {
this.root = root;
this.input = this.root.querySelector('.input');
this.form = this.root.querySelector('.todoForm');
this.form.addEventListener('keydown', this.submitForm);
this.todos = this.root.querySelector('.todos');
this.store = {
todos: [
{
id: Math.random() * 10000,
text: 'Banana',
state: COMPLETED,
},
{
id: Math.random() * 10000,
text: 'Ice cream',
state: ACTIVE
}
],
}
this.AllButton = this.root.querySelector('.All');
this.ActiveButton = this.root.querySelector('.Active');
this.CompletedButton = this.root.querySelector('.Completed');
this.display();
}
submitForm = (e) => {
if(e.key === 'Enter') {
e.preventDefault();
const typed = this.input.value;
const newTodo = {
id: Math.random * 10000,
text: typed,
state: ACTIVE
}
const newTodos = [...this.store.todos, newTodo];
this.store.todos = newTodos;
this.display();
this.input.value = ''
}
}
display = () => {
while(this.todos.firstChild) {
this.todos.removeChild(this.todos.firstChild)
}
this.store.todos.forEach(todo => {
const { id, text, state } = 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');
todoAndCheckBox.addEventListener('click', (e, todo) => this.clickHandler(e, todo));
this.displayCount(this.AllButton, ALL);
this.displayCount(this.ActiveButton, ACTIVE);
this.displayCount(this.CompletedButton, COMPLETED);
})
}
clickHandler = (e, todo) => {
e.currentTarget.classList.toggle('crossOut');
console.log(todo, 'todo')
todo.state = todo.state === COMPLETED ? ACTIVE : COMPLETED
}
displayCount = (button, type) => {
let count = 0;
if(type === ALL) {
count = this.store.todos.length;
button.innerText = `All: ${count}`;
}
if(type === ACTIVE) {
const filtered = this.store.todos.filter(todo => todo.state === ACTIVE);
count = filtered.length;
button.innerText = `Active: ${count}`;
}
if(type === COMPLETED) {
const filtered = this.store.todos.filter(todo => todo.state === ACTIVE);
count = filtered.length;
button.innerText = `Completed: ${count}`;
}
}
}
const root = document.querySelector('#root');
const instance = new displayTodos(root);
期望的结果是当我单击以划掉待办事项时,Active
和 Completed
按钮将显示适当的计数。但是,在这个函数中:
clickHandler = (e, todo) => {
e.currentTarget.classList.toggle('crossOut');
console.log(todo, 'todo')
todo.state = todo.state === COMPLETED ? ACTIVE : COMPLETED
}
我无法取出 todo
项。当我 console.log 它出来时,它说它是未定义的。我很困惑,因为我确实在这里使用了它:
todoAndCheckBox.addEventListener('click', (e, todo) => this.clickHandler(e, todo));
- 为什么我没有收到
todo
,我该怎么做才能解决这个问题?
- 我注意到如果我将该行重写为
todoAndCheckBox.addEventListener('click', this.clickHandler.bind(this, e, todo));
JS 抱怨 e
没有定义。我如何到达那里 e
?
您可以在侦听器中使用匿名函数。从那里您可以调用另一个函数或直接处理您的逻辑。
const otherFunction = (e) => {
console.log(todo); // global
console.log(e);
}
let todo = {
thing: 'stuff'
};
let todoAndCheckBox = document.getElementById('todoAndCheckBox');
todoAndCheckBox.addEventListener('click', (e) => otherFunction(e));
<button id='todoAndCheckBox'> click </button>
您只需要在侦听器中从匿名函数的参数中删除 todo
。
通过将 todo
作为参数传递,您将覆盖已经在范围内的 todo
,并且该函数正在指定一个未传递给它的参数。
试试这个:
todoAndCheckBox.addEventListener('click', (e) => this.clickHandler(e, todo));
我有以下代码: HTML:
<div id="root">
<form class="todoForm">
<input class="input" placeholder="What's gotta be done'?" />
</form>
<div class="todos"></div>
<div class="footer">
<button class="All">All</button>
<button class="Active">Active</button>
<button class="Completed">Completed</button>
<button class="Clear">Clear</button>
</div>
</div>
CSS:
.todoForm {
margin-bottom: 20px;
}
.todos {
margin-bottom: 20px;
}
.todo {
margin-bottom: 10px;
}
.todoAndCheckBox {
display: flex;
font-weight: bold;
}
.checkBox {
border-radius: 50%;
outline: green;
}
.crossOut {
font-weight: normal;
text-decoration: line-through
}
JS:
const COMPLETED = 'completed';
const ACTIVE = 'active';
const ALL = 'all';
class displayTodos {
constructor(root) {
this.root = root;
this.input = this.root.querySelector('.input');
this.form = this.root.querySelector('.todoForm');
this.form.addEventListener('keydown', this.submitForm);
this.todos = this.root.querySelector('.todos');
this.store = {
todos: [
{
id: Math.random() * 10000,
text: 'Banana',
state: COMPLETED,
},
{
id: Math.random() * 10000,
text: 'Ice cream',
state: ACTIVE
}
],
}
this.AllButton = this.root.querySelector('.All');
this.ActiveButton = this.root.querySelector('.Active');
this.CompletedButton = this.root.querySelector('.Completed');
this.display();
}
submitForm = (e) => {
if(e.key === 'Enter') {
e.preventDefault();
const typed = this.input.value;
const newTodo = {
id: Math.random * 10000,
text: typed,
state: ACTIVE
}
const newTodos = [...this.store.todos, newTodo];
this.store.todos = newTodos;
this.display();
this.input.value = ''
}
}
display = () => {
while(this.todos.firstChild) {
this.todos.removeChild(this.todos.firstChild)
}
this.store.todos.forEach(todo => {
const { id, text, state } = 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');
todoAndCheckBox.addEventListener('click', (e, todo) => this.clickHandler(e, todo));
this.displayCount(this.AllButton, ALL);
this.displayCount(this.ActiveButton, ACTIVE);
this.displayCount(this.CompletedButton, COMPLETED);
})
}
clickHandler = (e, todo) => {
e.currentTarget.classList.toggle('crossOut');
console.log(todo, 'todo')
todo.state = todo.state === COMPLETED ? ACTIVE : COMPLETED
}
displayCount = (button, type) => {
let count = 0;
if(type === ALL) {
count = this.store.todos.length;
button.innerText = `All: ${count}`;
}
if(type === ACTIVE) {
const filtered = this.store.todos.filter(todo => todo.state === ACTIVE);
count = filtered.length;
button.innerText = `Active: ${count}`;
}
if(type === COMPLETED) {
const filtered = this.store.todos.filter(todo => todo.state === ACTIVE);
count = filtered.length;
button.innerText = `Completed: ${count}`;
}
}
}
const root = document.querySelector('#root');
const instance = new displayTodos(root);
期望的结果是当我单击以划掉待办事项时,Active
和 Completed
按钮将显示适当的计数。但是,在这个函数中:
clickHandler = (e, todo) => {
e.currentTarget.classList.toggle('crossOut');
console.log(todo, 'todo')
todo.state = todo.state === COMPLETED ? ACTIVE : COMPLETED
}
我无法取出 todo
项。当我 console.log 它出来时,它说它是未定义的。我很困惑,因为我确实在这里使用了它:
todoAndCheckBox.addEventListener('click', (e, todo) => this.clickHandler(e, todo));
- 为什么我没有收到
todo
,我该怎么做才能解决这个问题? - 我注意到如果我将该行重写为
todoAndCheckBox.addEventListener('click', this.clickHandler.bind(this, e, todo));
JS 抱怨 e
没有定义。我如何到达那里 e
?
您可以在侦听器中使用匿名函数。从那里您可以调用另一个函数或直接处理您的逻辑。
const otherFunction = (e) => {
console.log(todo); // global
console.log(e);
}
let todo = {
thing: 'stuff'
};
let todoAndCheckBox = document.getElementById('todoAndCheckBox');
todoAndCheckBox.addEventListener('click', (e) => otherFunction(e));
<button id='todoAndCheckBox'> click </button>
您只需要在侦听器中从匿名函数的参数中删除 todo
。
通过将 todo
作为参数传递,您将覆盖已经在范围内的 todo
,并且该函数正在指定一个未传递给它的参数。
试试这个:
todoAndCheckBox.addEventListener('click', (e) => this.clickHandler(e, todo));