过滤器任务不起作用 - 使用 es6 类的 MVC 模式的待办事项列表



我正在尝试使用 MVC 模式用纯 JS 编写一个待办事项列表项目。这是我与MVC的第一个项目,我有一个无法解决的真正问题。 我有三个按钮,每个按钮都有一个值作为过滤器值(在模型类中(,用于完成活动和所有任务。筛选器的默认值为0,表示"全部"按钮。 当"完成"按钮处于活动状态时,"新建待办事项"将添加到页面,但该页面仅适用于"完成待办事项",并且"完成"页面仍处于活动状态时,"新建待办事项"必须添加到所有页面。 我写了一些方法来处理它,但它们不起作用,我无法理解问题出在哪里。 我该如何解决?

这是我的代码:

class Model {
constructor() {
this.todoS = [];
this.filter = 0;
}
bindTodoListChanged(callback) {
this.onTodoListChanged = callback;
}
_commit(todoS) {
this.onTodoListChanged(todoS);
}
addTodo(todoText) {
var todo = {
id:
this.todoS.length > 0
? this.todoS[this.todoS.length - 1].id + 1
: 0,
text: todoText,
complete: false
};
this.todoS.push(todo);
this._commit(this.todoS);
}
toggleTodo(id) {
this.todoS = this.todoS.map(todo =>
todo.id === id
? {
id: todo.id,
text: todo.text,
complete: !todo.complete
}
: todo
);
this._commit(this.todoS);
}
filterTodo(filter) {
this.todoS.filter(todo => {
if (filter === 0) return true;
return filter === 1 ? !todo.complete : todo.complete;
});
}
}
class View {
constructor() {
this.form = document.querySelector("#taskForm");
this.input = document.getElementById("taskInput");
this.list = document.querySelector("#taskList");
this.filterBtnS = document.getElementById("filterButtons");
this.allBtn = document.querySelector(".all");
this.activeBtn = document.querySelector(".active");
this.completeBtn = document.querySelector(".complete");
}
createElement(tag, className) {
var element = document.createElement(tag);
if (className) element.classList.add(className);
return element;
}
getElement(selector) {
var element = document.querySelector(selector);
return element;
}
get _todoText() {
return this.input.value;
}
_resetInput() {
this.input.value = "";
}
displayTodoS(todoS) {
// Faster way for clear tasks
while (this.list.firstChild) {
this.list.removeChild(this.list.firstChild);
}
if (todoS.length !== 0) {
todoS.forEach(todo => {
var li = this.createElement("li", "task"),
span = this.createElement("span");
li.id = todo.id;            
var checkbox = this.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = todo.complete;
if (todo.complete) {
var strike = this.createElement("s");
strike.textContent = todo.text;
span.innerHTML = "";    
span.append(strike);
} else {
span.textContent = todo.text;
}
li.append(checkbox, span);
this.list.append(li);
});
}
}
bindAddTodo(handler) {
this.form.addEventListener("submit", e => {
e.preventDefault();
if (this._todoText) {
handler(this._todoText);
this._resetInput();
} 
});
}

bindToggleTodo(handler) {
this.list.addEventListener("change", event => {
if (event.target.type === "checkbox") {
var id = +event.target.parentElement.id;
handler(id);
}
});
}
bindFilterTodo(handler) {
this.filterBtnS.addEventListener("click", e => {
var filter = +e.target.getAttribute("value");
handler(filter);
});
}
}
class Controller {
constructor(model, view) {
this.model = model;
this.view = view;
this.model.bindTodoListChanged(this.onTodoListChanged);
this.view.bindAddTodo(this.handleAddTodo);
this.view.bindToggleTodo(this.handleToggleTodo);
this.view.bindFilterTodo(this.handleFilterTodo);
this.onTodoListChanged(this.model.todoS);
}
onTodoListChanged = todoS => {
this.view.displayTodoS(todoS);
};
handleAddTodo = todoText => {
this.model.addTodo(todoText);
};
handleToggleTodo = id => {
this.model.toggleTodo(id);
};
handleFilterTodo = filter => {
this.model.filterTodo(filter);
};
}
var app = new Controller(new Model(), new View());
<div id="main">
<h2>Task List</h2>
<form id="taskForm">
<input
id="taskInput"
placeholder="New task..."
autocomplete="off"
/>
<input class="submit" type="submit" value="Add Task" />
</form>
<div id="filterButtons" class="buttons">
<div class="all" value="0">All</div>
<div class="active" value="1">Active</div>
<div class="complete" value="2">Completed</div>
</div>
<ul id="taskList"></ul>
</div>

问题是在filterTodo中,你只是过滤任务,而不是_commit更改。

所以

  1. 将筛选器存储在模型中
  2. 将过滤器移动到_commit(以便它将保留过滤器以进行任何其他操作,例如添加待办事项(

class Model {
constructor() {
this.todoS = [];
this.filter = 0;
}
bindTodoListChanged(callback) {
this.onTodoListChanged = callback;
}
_commit(todoS = this.todoS) {
this.onTodoListChanged(todoS.filter(todo => {
if (this.filter === 0) return true;
return this.filter === 1 ? !todo.complete : todo.complete;
}));
}
addTodo(todoText) {
var todo = {
id:
this.todoS.length > 0
? this.todoS[this.todoS.length - 1].id + 1
: 0,
text: todoText,
complete: false
};
this.todoS.push(todo);
this._commit(this.todoS);
}
toggleTodo(id) {
this.todoS = this.todoS.map(todo =>
todo.id === id
? {
id: todo.id,
text: todo.text,
complete: !todo.complete
}
: todo
);
this._commit(this.todoS);
}
filterTodo(filter) {
this.filter = filter;
this._commit();
}
}
class View {
constructor() {
this.form = document.querySelector("#taskForm");
this.input = document.getElementById("taskInput");
this.list = document.querySelector("#taskList");
this.filterBtnS = document.getElementById("filterButtons");
this.allBtn = document.querySelector(".all");
this.activeBtn = document.querySelector(".active");
this.completeBtn = document.querySelector(".complete");
}
createElement(tag, className) {
var element = document.createElement(tag);
if (className) element.classList.add(className);
return element;
}
getElement(selector) {
var element = document.querySelector(selector);
return element;
}
get _todoText() {
return this.input.value;
}
_resetInput() {
this.input.value = "";
}
displayTodoS(todoS) {
// Faster way for clear tasks
while (this.list.firstChild) {
this.list.removeChild(this.list.firstChild);
}
if (todoS.length !== 0) {
todoS.forEach(todo => {
var li = this.createElement("li", "task"),
span = this.createElement("span");
li.id = todo.id;            
var checkbox = this.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = todo.complete;
if (todo.complete) {
var strike = this.createElement("s");
strike.textContent = todo.text;
span.innerHTML = "";    
span.append(strike);
} else {
span.textContent = todo.text;
}
li.append(checkbox, span);
this.list.append(li);
});
}
}
bindAddTodo(handler) {
this.form.addEventListener("submit", e => {
e.preventDefault();
if (this._todoText) {
handler(this._todoText);
this._resetInput();
} 
});
}

bindToggleTodo(handler) {
this.list.addEventListener("change", event => {
if (event.target.type === "checkbox") {
var id = +event.target.parentElement.id;
handler(id);
}
});
}
bindFilterTodo(handler) {
this.filterBtnS.addEventListener("click", e => {
var filter = +e.target.getAttribute("value");
handler(filter);
});
}
}
class Controller {
constructor(model, view) {
this.model = model;
this.view = view;
this.model.bindTodoListChanged(this.onTodoListChanged);
this.view.bindAddTodo(this.handleAddTodo);
this.view.bindToggleTodo(this.handleToggleTodo);
this.view.bindFilterTodo(this.handleFilterTodo);
this.onTodoListChanged(this.model.todoS);
}
onTodoListChanged = todoS => {
console.log(todoS);
this.view.displayTodoS(todoS);
};
handleAddTodo = todoText => {
this.model.addTodo(todoText);
};
handleToggleTodo = id => {
this.model.toggleTodo(id);
};
handleFilterTodo = filter => {
this.model.filterTodo(filter);
};
}
var app = new Controller(new Model(), new View());
<div id="main">
<h2>Task List</h2>
<form id="taskForm">
<input id="taskInput" placeholder="New task..." autocomplete="off" />
<input class="submit" type="submit" value="Add Task" />
</form>
<div id="filterButtons" class="buttons">
<div class="all" value="0">All</div>
<div class="active" value="1">Active</div>
<div class="complete" value="2">Completed</div>
</div>
<ul id="taskList"></ul>
</div>

https://stackblitz.com/edit/js-1u6dxi

我怀疑值返回中最大的问题。例如:

handleFilterTodo = filter => {
this.model.filterTodo(filter);
};

此代码不返回任何内容,它只调用this.model.filterTodo。在相应的方法filterTodo中,您将使用this.todoS.filter创建一个新数组,但不会在任何地方返回它:

filterTodo(filter) {
this.todoS.filter(todo => {
if (filter === 0) return true;
return filter === 1 ? !todo.complete : todo.complete;
});
}

您可以执行类似于此处对toggleTodomap函数所做的操作:

filterTodo(filter) {
this.todoS = this.todoS.filter(todo => {
if (filter === 0) return true;
return filter === 1 ? !todo.complete : todo.complete;
});
}

。但这只能工作一次,因为设置过滤器会从数据库中删除其他待办事项。

根据我对代码的理解(没有尝试(,我可能只会设置过滤器,每当调用_commit时,都会根据所选过滤器传递过滤版本的待办事项

constructor() {
...
this.possibleFilters = {
0: () => true,
1: todo => !todo.completed,
2: todo => todo.completed
};
}
filterTodo(filter) {
this.filter = filter;
}
_commit(todoS) {
const selectedFilter = this.possibleFilters[this.filter];
this.onTodoListChanged(todoS.filter(selectedFilter));
}

最新更新