随附的代码段是针对CS50移动应用开发者的作业问题的已发布解决方案。我对一个功能感到困惑。
Todo.prototype.toggleCheck = function() {
this.checked = !this.checked
if (this.element && this.checkbox) {
this.checkbox.checked = this.checked
} else {
this.element = renderTodo(this)
}
}
似乎不需要if else语句。注意:在renderTodo函数中checkbox.checked = todo.checked
如果我们删除该条件程序,该程序似乎可以正常运行。我想念什么吗?
const classNames = {
DELETE_BUTTON: 'delete-button',
TODO_ITEM: 'todo-container',
TODO_CHECKBOX: 'todo-checkbox',
TODO_TEXT: 'todo-text',
}
const list = document.getElementById('todo-list')
const itemCountDiv = document.getElementById('item-count')
const uncheckedCountDiv = document.getElementById('unchecked-count')
let todos = []
function count(arr, fn) {
return arr.reduce((acc, next) => fn(next) ? acc + 1 : acc, 0)
}
function Todo(name) {
this.name = name || 'New TODO'
this.checked = false
this.element = null
this.checkbox = null
}
Todo.prototype.toggleCheck = function() {
this.checked = !this.checked
if (this.element && this.checkbox) {
this.checkbox.checked = this.checked
} else {
this.element = renderTodo(this)
}
}
function renderTodo(todo) {
if (todo.element) return todo.element
const deleteButton = document.createElement('button')
deleteButton.innerHTML = '×'
deleteButton.className = classNames.DELETE_BUTTON
// keep reference of todo on button so that it can be dereferenced in the callback
deleteButton.onclick = removeTodo
deleteButton.todoRef = todo
const checkbox = document.createElement('input')
checkbox.className = classNames.TODO_CHECKBOX
checkbox.type = 'checkbox'
checkbox.checked = todo.checked
checkbox.todoRef = todo
checkbox.onchange = toggleChecked
const span = document.createElement('span')
span.className = classNames.TODO_TEXT
span.setAttribute('contenteditable', 'true')
span.innerHTML = todo.name
const li = document.createElement('li')
li.className = classNames.TODO_ITEM
li.appendChild(deleteButton)
li.appendChild(checkbox)
li.appendChild(span)
// keep reference of element on todo for performance
todo.element = li
todo.checkbox = checkbox
return li
}
function render() {
list.innerHTML = ''
todos.map(renderTodo).forEach(todo => list.appendChild(todo))
uncheckedCountDiv.innerHTML = count(todos, todo => !todo.checked)
itemCountDiv.innerHTML = todos.length
return false
}
function addTodo(name) {
const todo = new Todo(name)
todos.push(todo)
return render()
}
function toggleChecked() {
this.todoRef.toggleCheck()
return render()
}
function removeTodo() {
const todo = this.todoRef
todos = todos.filter(t => t !== todo)
return render()
}
* {
box-sizing: border-box;
}
html, body {
background-color: #eee;
margin: 0;
padding: 0;
}
ul {
margin: 0;
padding: 0;
list-style-type: none;
}
.center {
align-self: center;
}
.flow-right {
display: flex;
justify-content: space-around;
}
.container {
max-width: 800px;
margin: 0 auto;
padding: 10px;
display: flex;
flex-direction: column;
background-color: white;
height: 100vh;
}
.title, .controls, .button {
flex: none;
}
.button {
padding: 10px 20px;
}
.todo-list {
flex: 1 1 0;
margin-top: 20px;
padding: 20px;
overflow-y: auto;
}
.delete-button {
margin: 10px;
}
.todo-checkbox {
margin: 10px;
}
.todo-container {
padding: 20px;
border-bottom: 1px solid #333;
}
.todo-container:first-of-type {
border-top: 1px solid #333;
}
<!DOCTYPE html>
<html>
<head>
<title>TODO App</title>
<body>
<div class="container center">
<h1 class="center title">My TODO App</h1>
<div class="flow-right controls">
<span>Item count: <span id="item-count">0</span></span>
<span>Unchecked count: <span id="unchecked-count">0</span></span>
</div>
<button class="button center" onClick="addTodo()">New TODO</button>
<ul id="todo-list" class="todo-list"></ul>
</div>
</body>
</html>