123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>代办事项</title>
- <script src="./babel.min.js"></script>
- <script src="./react.development.js"></script>
- <script src="./react-dom.development.js"></script>
- <link rel="stylesheet" href="./index.css" />
- </head>
- <body>
- <div id="root"></div>
- <script type="text/babel">
- function App() {
- return (
- <>
- <TodoApp />
- </>
- );
- }
- class TodoApp extends React.Component {
- constructor() {
- super();
- this.state = {
- todos: [
- {
- id: 1,
- title: '吃饭',
- completed: false,
- },
- {
- id: 2,
- title: '睡觉',
- completed: true,
- },
- ], // 所有代办, 默认值 为 []
- filters: 'all', // 过滤条件 值为 "all | active | completed", 默认值 all
- };
- this.clearCompletedTodos = this.clearCompletedTodos.bind(this);
- this.removeTodoById = this.removeTodoById.bind(this);
- this.toggleTodoStatus = this.toggleTodoStatus.bind(this);
- }
- toggleTodoStatus(id) {
- this.setState(({ todos }) => {
- for (var i = 0, l = todos.length; i < l; i++) {
- if (todos[i].id === id) {
- todos[i].completed = !todos[i].completed;
- break;
- }
- }
- return {
- todos,
- };
- });
- }
- removeTodoById(id) {
- if (!confirm('确定删除当前代办吗?')) return;
- this.setState((prevState) => ({
- todos: prevState.todos.filter((todo) => todo.id !== id),
- }));
- }
- clearCompletedTodos() {
- if (!confirm('确定清楚所有已完成的代办吗?')) return;
- this.setState((prevState) => ({
- todos: prevState.todos.filter((todo) => !todo.completed),
- }));
- }
- 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;
- if (filters === 'all') return todos;
- // return todos.filter((todo) =>
- // filters === 'active'
- // ? todo.completed === false
- // : todo.completed === true
- // );
- return todos.filter((todo) =>
- filters === 'active' ? !todo.completed : todo.completed
- );
- }
- render() {
- // console.log(`output->render`);
- return (
- <section className="todoapp">
- <TodoHeader addTodo={this.addTodo.bind(this)} />
- <TodoMain
- todos={this.renderTodos()}
- toggleAll={this.toggleAllTodoStatus.bind(this)}
- remove={this.removeTodoById}
- toggle={this.toggleTodoStatus}
- />
- <TodoFooter
- undoneCount={this.calcUndoneTodoCount()}
- setFilters={this.setFilters.bind(this)}
- filter={this.state.filters}
- clear={this.clearCompletedTodos}
- />
- </section>
- );
- }
- }
- function TodoHeader({ addTodo }) {
- return (
- <header className="header">
- <h1>todos</h1>
- <input
- autoFocus="autofocus"
- 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, toggle, remove, toggleAll }) {
- return (
- <section className="main">
- <input
- id="toggle-all"
- type="checkbox"
- className="toggle-all"
- onChange={(e) => {
- toggleAll(e.target.checked);
- }}
- />
- <label htmlFor="toggle-all"></label>
- <ul className="todo-list">
- {todos &&
- todos.map((todo) => (
- <TodoItem
- key={todo.id}
- todo={todo}
- onRemove={remove}
- onToggle={toggle}
- />
- ))}
- </ul>
- </section>
- );
- }
- function TodoFooter({ undoneCount, setFilters, filter, clear }) {
- return (
- <footer className="footer">
- <span className="todo-count">
- <strong>{undoneCount}</strong> items left
- </span>
- <ul className="filters">
- <li>
- <a
- href="#/all"
- className={filter === 'all' ? 'selected' : ''}
- onClick={() => {
- setFilters('all');
- }}
- >
- All
- </a>
- </li>
- <li>
- <a
- href="#/active"
- className={filter === 'active' ? 'selected' : ''}
- onClick={() => {
- setFilters('active');
- }}
- >
- Active
- </a>
- </li>
- <li>
- <a
- href="#/completed"
- className={filter === 'completed' ? 'selected' : ''}
- onClick={() => {
- setFilters('completed');
- }}
- >
- Completed
- </a>
- </li>
- </ul>
- <button className="clear-completed" onClick={clear}>
- Clear completed
- </button>
- </footer>
- );
- }
- function TodoItem({ todo, onRemove, onToggle }) {
- return (
- <li className="todo">
- <div className="view">
- <input
- type="checkbox"
- className="toggle"
- checked={todo.completed}
- onChange={() => onToggle(todo.id)}
- />
- <label>{todo.title}</label>
- <button
- className="destroy"
- onClick={() => onRemove(todo.id)}
- ></button>
- </div>
- </li>
- );
- }
- const root = ReactDOM.createRoot(document.getElementById('root'));
- root.render(<App />);
- </script>
- </body>
- </html>
|