index.html 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>Document</title>
  7. <script src="../babel.min.js"></script>
  8. <script src="../react.development.js"></script>
  9. <script src="../react-dom.development.js"></script>
  10. <link rel="stylesheet" href="./index.css" />
  11. </head>
  12. <body>
  13. <div id="root"></div>
  14. <script type="text/babel">
  15. const root = ReactDOM.createRoot(document.getElementById("root"));
  16. function App() {
  17. return (
  18. <div>
  19. <Box />
  20. </div>
  21. );
  22. }
  23. class Box extends React.Component {
  24. constructor() {
  25. super();
  26. this.state = {
  27. todos: [
  28. {
  29. id: 1,
  30. title: "吃饭",
  31. completed: true,
  32. },
  33. {
  34. id: 2,
  35. title: "睡觉",
  36. completed: false,
  37. },
  38. ],
  39. filters: "all",
  40. };
  41. }
  42. // 渲染todo列表
  43. renderTodos() {
  44. let { todos, filters } = this.state;
  45. // 如果 filters是all 显示全部的todos
  46. if (filters === "all") return todos;
  47. return todos.filter((todo) =>
  48. filters === 'active' ? !todo.completed : todo.completed
  49. );
  50. }
  51. // 添加内容
  52. addMain(value) {
  53. this.setState((prevState) => ({
  54. todos: [
  55. ...prevState.todos,
  56. {
  57. id: Date.now(),
  58. title: value,
  59. completed: false,
  60. },
  61. ],
  62. }));
  63. }
  64. // 选择哪项
  65. chooseMain(ids) {
  66. let { todos } = this.state;
  67. this.setState((prevState) => {
  68. for (var i = 0; i < todos.length; i++) {
  69. if (todos[i].id === ids) {
  70. todos[i].completed = !todos[i].completed;
  71. }
  72. }
  73. return { todos };
  74. });
  75. }
  76. // 删除选项
  77. removeMain(ids) {
  78. if (!confirm("您确定删除么")) {
  79. return;
  80. }
  81. let { todos } = this.state;
  82. this.setState((prev) => ({
  83. todos: prev.todos.filter((t) => {
  84. return t.id !== ids;
  85. }),
  86. }));
  87. }
  88. // 勾选
  89. allChoose(isCheck) {
  90. let { todos } = this.state;
  91. this.setState((prev) => ({
  92. todos: prev.todos.map((ele) => {
  93. ele.completed = isCheck;
  94. return ele;
  95. }),
  96. }));
  97. }
  98. // 未选中的
  99. countUnSelected() {
  100. return this.state.todos.filter((ele) => !ele.completed).length;
  101. }
  102. // 设置过滤项
  103. setFilters(text) {
  104. this.setState({
  105. filters: text,
  106. });
  107. }
  108. // 清除所有完成项
  109. clearCompletedTodo() {
  110. if (!confirm('确定清除所有完成项吗?')) return;
  111. this.setState((prevState) => ({
  112. todos: prevState.todos.filter((todo) => !todo.completed),
  113. }));
  114. }
  115. render() {
  116. return (
  117. <section className="todoapp">
  118. <Header addList={this.addMain.bind(this)} />
  119. <Main
  120. todos={this.renderTodos()}
  121. choose={this.chooseMain.bind(this)}
  122. remove={this.removeMain.bind(this)}
  123. all={this.allChoose.bind(this)}
  124. />
  125. <Footer
  126. count={this.countUnSelected()}
  127. setFilters={this.setFilters.bind(this)}
  128. filter={this.state.filters}
  129. clear={this.clearCompletedTodo.bind(this)}
  130. />
  131. </section>
  132. );
  133. }
  134. }
  135. function Header({ addList }) {
  136. return (
  137. <header className="header">
  138. <h1>todos</h1>
  139. <input
  140. autoFocus="autofocus"
  141. autoComplete="off"
  142. placeholder="输入您要完成的任务?"
  143. className="new-todo"
  144. onKeyUp={(e) => {
  145. if (e.keyCode === 13) {
  146. addList(e.target.value);
  147. e.target.value = "";
  148. }
  149. }}
  150. />
  151. </header>
  152. );
  153. }
  154. function Main({ todos, choose, remove, all }) {
  155. return (
  156. <section className="main">
  157. <input
  158. id="toggle-all"
  159. type="checkbox"
  160. onChange={(e) => {
  161. all(e.target.checked);
  162. }}
  163. className="toggle-all"
  164. />
  165. <label htmlFor="toggle-all"></label>
  166. <ul className="todo-list">
  167. {todos &&
  168. todos.map((ele) => (
  169. <Item
  170. key={ele.id}
  171. todo={ele}
  172. onChoose={choose}
  173. onRemove={remove}
  174. />
  175. ))}
  176. </ul>
  177. </section>
  178. );
  179. }
  180. function Item({ todo, onChoose, onRemove }) {
  181. return (
  182. <li className="todo">
  183. <div className="view">
  184. <input
  185. type="checkbox"
  186. checked={todo.completed}
  187. className="toggle"
  188. onChange={() => onChoose(todo.id)}
  189. />
  190. <label>{todo.title}</label>
  191. <button
  192. className="destroy"
  193. onClick={() => onRemove(todo.id)}
  194. ></button>
  195. </div>
  196. <input type="text" className="edit" />
  197. </li>
  198. );
  199. }
  200. function Footer({ count, setFilters, filter, clear }) {
  201. return (
  202. <footer className="footer">
  203. <span className="todo-count">
  204. <strong>{count}</strong> items left{" "}
  205. </span>
  206. <ul className="filters">
  207. <li>
  208. <a
  209. href="#/all"
  210. className={filter === "all" ? "selected" : ""}
  211. onClick={() => {
  212. setFilters("all");
  213. }}
  214. >
  215. All
  216. </a>
  217. </li>
  218. <li>
  219. <a
  220. href="#/active"
  221. className={filter === "active" ? "selected" : ""}
  222. onClick={() => {
  223. setFilters("active");
  224. }}
  225. >
  226. Active
  227. </a>
  228. </li>
  229. <li>
  230. <a
  231. href="#/completed"
  232. className={filter === "completed" ? "selected" : ""}
  233. onClick={() => {
  234. setFilters("completed");
  235. }}
  236. >
  237. Completed
  238. </a>
  239. </li>
  240. </ul>
  241. <button className="clear-completed" onClick={clear}>
  242. Clear completed
  243. </button>
  244. </footer>
  245. );
  246. }
  247. root.render(<App />);
  248. </script>
  249. </body>
  250. </html>