|
@@ -41,6 +41,36 @@
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+ setFilters(text) {
|
|
|
+ this.setState({
|
|
|
+ filters: text,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ addTodo(title) {
|
|
|
+ // 注意:this 必须是 组件实例
|
|
|
+ this.setState((prevState) => ({
|
|
|
+ todos: [
|
|
|
+ ...prevState.todos,
|
|
|
+ { id: Date.now(), title, completed: false },
|
|
|
+ ],
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ toggleAllTodoStatus(completed) {
|
|
|
+ // 注意:this 必须是 组件实例
|
|
|
+ this.setState((prevState) => ({
|
|
|
+ todos: prevState.todos.map((todo) => {
|
|
|
+ todo.completed = completed;
|
|
|
+ return todo;
|
|
|
+ }),
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ calcUndoneTodoCount() {
|
|
|
+ return this.state.todos.filter((todo) => !todo.completed).length;
|
|
|
+ }
|
|
|
+
|
|
|
// 根据filters,todos得到过滤后的代办数组
|
|
|
renderTodos() {
|
|
|
let { todos, filters } = this.state;
|
|
@@ -58,17 +88,25 @@
|
|
|
}
|
|
|
|
|
|
render() {
|
|
|
+ // console.log(`output->render`);
|
|
|
return (
|
|
|
<section className="todoapp">
|
|
|
- <TodoHeader />
|
|
|
- <TodoMain todos={this.renderTodos()} />
|
|
|
- <TodoFooter />
|
|
|
+ <TodoHeader addTodo={this.addTodo.bind(this)} />
|
|
|
+ <TodoMain
|
|
|
+ todos={this.renderTodos()}
|
|
|
+ toggle={this.toggleAllTodoStatus.bind(this)}
|
|
|
+ />
|
|
|
+ <TodoFooter
|
|
|
+ undoneCount={this.calcUndoneTodoCount()}
|
|
|
+ setFilters={this.setFilters.bind(this)}
|
|
|
+ filter={this.state.filters}
|
|
|
+ />
|
|
|
</section>
|
|
|
);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- function TodoHeader() {
|
|
|
+ function TodoHeader({ addTodo }) {
|
|
|
return (
|
|
|
<header className="header">
|
|
|
<h1>todos</h1>
|
|
@@ -77,14 +115,33 @@
|
|
|
autoComplete="off"
|
|
|
placeholder="输入您要完成的任务?"
|
|
|
className="new-todo"
|
|
|
+ onKeyUp={(e) => {
|
|
|
+ // 判断按下enter
|
|
|
+ // console.log(`output->e`, e);
|
|
|
+ if (e.which === 13) {
|
|
|
+ let title = e.target.value.trim();
|
|
|
+
|
|
|
+ if (!title) return alert('您输入的代办名称不合法!');
|
|
|
+
|
|
|
+ addTodo(title);
|
|
|
+ e.target.value = '';
|
|
|
+ }
|
|
|
+ }}
|
|
|
/>
|
|
|
</header>
|
|
|
);
|
|
|
}
|
|
|
- function TodoMain({ todos }) {
|
|
|
+ function TodoMain({ todos, toggle }) {
|
|
|
return (
|
|
|
<section className="main">
|
|
|
- <input id="toggle-all" type="checkbox" className="toggle-all" />
|
|
|
+ <input
|
|
|
+ id="toggle-all"
|
|
|
+ type="checkbox"
|
|
|
+ className="toggle-all"
|
|
|
+ onChange={(e) => {
|
|
|
+ toggle(e.target.checked);
|
|
|
+ }}
|
|
|
+ />
|
|
|
<label htmlFor="toggle-all"></label>
|
|
|
<ul className="todo-list">
|
|
|
{todos &&
|
|
@@ -93,25 +150,43 @@
|
|
|
</section>
|
|
|
);
|
|
|
}
|
|
|
- function TodoFooter() {
|
|
|
+ function TodoFooter({ undoneCount, setFilters, filter }) {
|
|
|
return (
|
|
|
<footer className="footer">
|
|
|
<span className="todo-count">
|
|
|
- <strong>0</strong> items left
|
|
|
+ <strong>{undoneCount}</strong> items left
|
|
|
</span>
|
|
|
<ul className="filters">
|
|
|
<li>
|
|
|
- <a href="#/all" className="selected">
|
|
|
+ <a
|
|
|
+ href="#/all"
|
|
|
+ className={filter === 'all' ? 'selected' : ''}
|
|
|
+ onClick={() => {
|
|
|
+ setFilters('all');
|
|
|
+ }}
|
|
|
+ >
|
|
|
All
|
|
|
</a>
|
|
|
</li>
|
|
|
<li>
|
|
|
- <a href="#/active" className="">
|
|
|
+ <a
|
|
|
+ href="#/active"
|
|
|
+ className={filter === 'active' ? 'selected' : ''}
|
|
|
+ onClick={() => {
|
|
|
+ setFilters('active');
|
|
|
+ }}
|
|
|
+ >
|
|
|
Active
|
|
|
</a>
|
|
|
</li>
|
|
|
<li>
|
|
|
- <a href="#/completed" className="">
|
|
|
+ <a
|
|
|
+ href="#/completed"
|
|
|
+ className={filter === 'completed' ? 'selected' : ''}
|
|
|
+ onClick={() => {
|
|
|
+ setFilters('completed');
|
|
|
+ }}
|
|
|
+ >
|
|
|
Completed
|
|
|
</a>
|
|
|
</li>
|