一、写UI界面

UI.png

  1. //app.component.html
  2. <div class="wrap">
  3. <div class="head">
  4. <div class="logo-add center">
  5. <p class="logo">ToDoList</p>
  6. <input class="add" type="text" placeholder="添加ToDo" />
  7. </div>
  8. </div>
  9. <div class="content center">
  10. <div class="todoing">
  11. <div class="head-count">
  12. <h2>正在进行</h2>
  13. <span class="todocount">1</span>
  14. </div>
  15. <ol class="todolist">
  16. <li>
  17. <input type="checkbox" />
  18. <p class="list">Html</p>
  19. <a href="#" class="del">-</a>
  20. </li>
  21. </ol>
  22. </div>
  23. <div class="todone">
  24. <div class="head-count">
  25. <h2>已经完成</h2>
  26. <span class="todocount">1</span>
  27. </div>
  28. <ol class="todolist todolistStyle">
  29. <li>
  30. <input type="checkbox" />
  31. <p class="list">css</p>
  32. <a href="#" class="del">-</a>
  33. </li>
  34. </ol>
  35. </div>
  36. </div>
  37. </div>
  1. //app.component.css
  2. .wrap{
  3. width: 100%;
  4. position: fixed;
  5. left: 0;
  6. right: 0;
  7. top: 0;
  8. bottom: 0;
  9. background-color: #CDCDCD;
  10. }
  11. .center{
  12. width: 600px;
  13. }
  14. .head{
  15. width: 100%;
  16. height: 50px;
  17. background-color: #323232;
  18. position: relative;
  19. }
  20. .logo-add{
  21. height: 50px;
  22. line-height: 50px;
  23. /* background-color: orange; */
  24. position: absolute;
  25. left: 50%;
  26. transform: translateX(-50%);
  27. display: flex;
  28. justify-content: space-between;
  29. }
  30. .logo{
  31. width: 100px;
  32. line-height: 50px;
  33. color: #DDD;
  34. font-size: 24px;
  35. cursor: pointer;
  36. font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
  37. }
  38. .add{
  39. width: 360px;
  40. height: 24px;
  41. margin-top: 12px;
  42. text-indent: 10px;
  43. border-radius: 5px;
  44. box-shadow: 0 1px 0 rgba(255,255,255,0.24), 0 1px 6px rgba(0,0,0,0.45) inset;
  45. border: none;
  46. outline: none;
  47. }
  48. .content{
  49. position: absolute;
  50. left: 50%;
  51. transform: translateX(-50%);
  52. }
  53. .head-count{
  54. height: 31px;
  55. display: flex;
  56. justify-content: space-between;
  57. align-items: center;
  58. margin: 20px 0;
  59. }
  60. .todocount{
  61. padding: 0 5px;
  62. height: 20px;
  63. border-radius: 20px;
  64. background: #E6E6FA;
  65. line-height: 22px;
  66. text-align: center;
  67. color: #666;
  68. font-size: 14px;
  69. font-weight: bold;
  70. }
  71. .todolist li{
  72. height: 32px;
  73. line-height: 32px;
  74. background: #fff;
  75. position: relative;
  76. margin-bottom: 10px;
  77. border-radius: 3px;
  78. border-left: 5px solid #629A9C;
  79. box-shadow: 0 1px 2px rgba(0,0,0,0.07);
  80. list-style: none;
  81. display: flex;
  82. align-items: center;
  83. }
  84. input[type="checkbox"]{
  85. background-color: initial;
  86. -webkit-appearance: checkbox;
  87. box-sizing: border-box;
  88. margin: 3px 3px 3px 14px;
  89. padding: initial;
  90. border: initial;
  91. width: 22px;
  92. height: 22px;
  93. }
  94. .list{
  95. width: 500px;
  96. padding-left: 6px;
  97. }
  98. .del{
  99. position: absolute;
  100. right: 5px;
  101. width: 14px;
  102. height: 12px;
  103. border-radius: 14px;
  104. border: 6px double #FFF;
  105. background: #CCC;
  106. line-height: 14px;
  107. text-align: center;
  108. color: #FFF;
  109. font-weight: bold;
  110. font-size: 14px;
  111. }
  112. .todolistStyle li{
  113. border-left: 5px solid #999;
  114. background-color: #E6E6E6;
  115. }
  116. .todolistStyle .list{
  117. color: #666;
  118. }
  119. .todolistStyle .del{
  120. border: 6px double #E6E6E6;
  121. }

二、功能实现

1、实现添加ToDo的功能

1-1、(keyup.enter)—回车获取input输入框的值

  1. //app.component.html
  2. input class="add" type="text" placeholder="添加ToDo"
  3. #add (keyup.enter)="handleEnter(add.value)" />
  1. //app.component.ts
  2. export class AppComponent {
  3. title = 'my-ng-todolist';
  4. public value:string = '';
  5. handleEnter(value:string){
  6. console.log(value)
  7. }
  8. }

1-2、将得到的值放进数组

  1. //定义一个对象装入value和选中状态
  2. //定义两个数组放不同状态的对象
  1. //app.component.ts
  2. export class AppComponent {
  3. title = 'my-ng-todolist';
  4. public value:string = '';
  5. public todoList:any [] = [];
  6. public doneList:any [] = [];
  7. handleEnter(value:string){
  8. console.log(value)
  9. let todoObj = {
  10. todo:value,
  11. check:false
  12. }
  13. this.todoList.push(todoObj)
  14. }
  15. }

1-3、enter后清空输入框的值

  1. //app.component.ts
  2. export class AppComponent {
  3. title = 'my-ng-todolist';
  4. ...
  5. handleEnter(value:string){
  6. ...
  7. this.value = ''
  8. }
  9. }
  1. //发现this.value = ''这行代码没有生效
  2. //把value的值绑定到输入框中---[(ngModel)]='value'
  3. //app.component.html
  4. <input class="add" type="text" placeholder="添加ToDo"
  5. #add (keyup.enter)="handleEnter(add.value)" [(ngModel)]='value'/>
  1. 报错了

c.png

  1. 解决报错
  2. //app.module.ts
  3. import { FormsModule } from '@angular/forms';
  4. @NgModule({
  5. ...,
  6. imports: [
  7. ...,
  8. FormsModule
  9. ],
  10. ...
  11. })

1-4、获取数组的长度+循环数组渲染页面

  1. //app.component.html
  2. <div class="todoing">
  3. <div class="head-count">
  4. <h2>正在进行</h2>
  5. <span class="todocount">{{this.todoList.length}}</span>
  6. </div>
  7. <ol class="todolist" *ngFor="let item of todoList">
  8. <li>
  9. <input type="checkbox" />
  10. <p class="list">{{item.todo}}</p>
  11. <a href="#" class="del">-</a>
  12. </li>
  13. </ol>
  14. </div>
  1. <div class="todone">
  2. <div class="head-count">
  3. <h2>已经完成</h2>
  4. <span class="todocount">{{this.doneList.length}}</span>
  5. </div>
  6. <ol class="todolist" *ngFor="let item of doneList">
  7. <li>
  8. <input type="checkbox" />
  9. <p class="list">{{item.todo}}</p>
  10. <a href="#" class="del">-</a>
  11. </li>
  12. </ol>
  13. </div>
  1. //添加ToDo功能完成

2、实现点击checkbox切换的功能

2-1、给数组循环加上index

  1. //app.component.html
  2. //todoList
  3. <ol class="todolist" *ngFor="let item of todoList;let key = index">...</ol>
  4. //doneList
  5. <ol class="todolist" *ngFor="let item of doneList;let key = index">...</ol>

2-2、给input加上事件

  1. //todoList
  2. <input type="checkbox" (click)="changeTodo(key,true)" />
  3. //doneList
  4. //checked='checked'---使checkbox处于选中状态
  5. <input type="checkbox" (click)="changeTodo(key,false)" checked='checked'/>

2-3、事件实现

  1. changeTodo(index,check){
  2. if(check){
  3. this.doneList.push(this.todoList[index]);
  4. this.todoList.splice(index,1);
  5. }else{
  6. this.todoList.push(this.doneList[index]);
  7. this.doneList.splice(index,1);
  8. }
  9. }
  1. //完成实现点击checkbox切换的功能

3、实现删除功能

3-1、添加事件

  1. //todoList
  2. <a href="#" class="del" (click)="handleDel(key,true)">-</a>
  3. //doneList
  4. <a href="#" class="del" (click)="handleDel(key,false)">-</a>

3-2、事件实现

  1. handleDel(index,check){
  2. if(check){
  3. this.todoList.splice(index,1);
  4. }else{
  5. this.doneList.splice(index,1);
  6. }
  7. }
  1. //完成删除功能

三、数据持久化

1、创建服务

  1. ng g service services/storage
  1. //services/storage.service.ts
  2. export class StorageService {
  3. constructor() { }
  4. setItem(key,value){
  5. localStorage.setItem(key,JSON.stringify(value))
  6. }
  7. getItem(key){
  8. return JSON.parse(localStorage.getItem(key))
  9. }
  10. }

1-1、导入服务

  1. import {StorageService} from './services/storage.service'

1-2、注入服务

  1. constructor(private storage:StorageService){ };

2、将数据存到localStorage

  1. handleEnter(value:string){
  2. console.log(value)
  3. let todoObj = {
  4. todo:value,
  5. check:false
  6. }
  7. var tempList = this.storage.getItem('todoList');
  8. if(tempList){
  9. tempList.push(todoObj)
  10. this.storage.setItem('todoList',tempList);
  11. }else{
  12. var tempData = []
  13. tempData.push(todoObj)
  14. this.storage.setItem('todoList',tempData);
  15. }
  16. this.todoList.push(todoObj)
  17. this.value = ''
  18. }
  19. changeTodo(index,check){
  20. if(check){
  21. this.doneList.push(this.todoList[index]);
  22. this.todoList.splice(index,1);
  23. this.storage.setItem('todoList',this.todoList)
  24. this.storage.setItem('doneList',this.doneList)
  25. }else{
  26. this.todoList.push(this.doneList[index]);
  27. this.doneList.splice(index,1);
  28. this.storage.setItem('todoList',this.todoList)
  29. this.storage.setItem('doneList',this.doneList)
  30. }
  31. }
  32. handleDel(index,check){
  33. if(check){
  34. this.todoList.splice(index,1);
  35. this.storage.setItem('todoList',this.todoList)
  36. }else{
  37. this.doneList.splice(index,1);
  38. this.storage.setItem('doneList',this.doneList)
  39. }
  40. }

3、初始事件

  1. initTodo(){
  2. var todoArr = this.storage.getItem('todoList');
  3. if(todoArr){
  4. this.todoList = todoArr
  5. }
  6. var doneArr = this.storage.getItem('doneList');
  7. if(doneArr){
  8. this.doneList = doneArr
  9. }
  10. }
  1. ngOnInit(){
  2. this.initTodo();
  3. }

4、清除数据

  1. <div class="content center">
  2. ...
  3. <p class="bottom">呼!终于完成了!!!
  4. <a href="#" class="clear" (click)="clearData()">clear</a>
  5. </p>
  6. </div>
  1. .bottom{
  2. text-align: center;
  3. font-size: 14px;
  4. color: #666;
  5. }
  6. .clear{
  7. color: #666;
  8. text-decoration: none;
  9. }
  10. .clear:hover{
  11. color:#629A9C;
  12. }
  1. clearData(){
  2. localStorage.clear();
  3. this.todoList = [];
  4. this.doneList = [];
  5. }