#javascript #forms #binding #onclick #this
Вопрос:
У меня есть следующий код: 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
предмет. Когда я утешаю.выйдите из системы, там написано, что она не определена. Я в замешательстве, потому что я передал это здесь, используя:
todoAndCheckBox.addEventListener('click', (e, todo) => this.clickHandler(e, todo));
- Почему я не получаю
todo
этого и что я могу сделать, чтобы обойти это? - Я заметил, что если я перепишу эту строку на
todoAndCheckBox.addEventListener('click', this.clickHandler.bind(this, e, todo));
JS жалуется, что e
это не определено. Как мне e
туда добраться?
Ответ №1:
Вам просто нужно удалить todo
параметры анонимной функции из прослушивателя.
Передавая в todo
качестве параметра, вы перезаписываете todo
то, что уже находится в области видимости, и функция определяет аргумент, который ей не передается.
Попробуйте это:
todoAndCheckBox.addEventListener('click', (e) => this.clickHandler(e, todo));
Ответ №2:
Вы можете использовать анонимную функцию в своем слушателе. Оттуда вы можете вызвать другую функцию или напрямую обработать свою логику.
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>
Комментарии:
1. Как я могу сделать то же самое, но с использованием отдельной функции? И почему
todo
не было принято, когда это делалось в первую очередь?2. Вам понадобится анонимная функция для записи события
e
— оттуда вы можете вызвать другую функцию. Я немного сократил свой код, чтобы проиллюстрировать это. addEventListener принимает один аргумент, которым является событие. Так что сначала вы должны запечатлеть это. Являетсяtodo
ли это глобальным? Или есть причина, по которой вам нужно передать его через функцию?