参考:https://segmentfault.com/a/1190000013519099
文章目录
效果:
准备工作
创建项目:ng new my-app
导航到workspace 文件夹:cd my-app
启动这个项目:ng serve --open
创建组件:ng generate component component/todoList
组件的路径是:
创建了组件后,要把它在根组件配置(app.module.ts
):
根据TS文件todo-list.component.ts
,我们创建的todoList这个组件的名字叫做:app-todo-list
。把组件引入到总页面中(app.component.html
),启动服务看看。成功!到这里我们已经知道组件怎么创建和引用了。
接下来开始写TodoList!
header
效果:
html
<!-- todo-list.component.html -->
<header>
<section>
<label for="title">TodoList</label>
<input type="text" placeholder="添加ToDo">
</section>
</header>
css
/* todo-list.component.css */
header {
height: 70px;
background-color: #333;
}
header section{
display: flex;
justify-content: space-between;
}
section {
margin: 0 auto;
width: 70vw;
}
header section label {
font-size: 28px;
color: #fff;
line-height: 70px;
}
header section input {
width: 35%;
margin: 10px 0;
padding-left: 15px;
border-radius: 10px;
box-shadow: 0 1px 0 rgba(255,255,255,0.24), 0 1px 6px rgba(0,0,0,0.45) inset;
}
Todo、Doing、Done
样式(HTML+CSS)
效果大致是这样:
一些细节
复选框与文字对齐
css
.item .listItem input[type=checkbox] {
width: 23px;
height: 23px;
/* 复选框与文字对齐 */
display: inline-block;
vertical-align: middle;
margin: 0 10px 2px;
}
给Done的item设置阴影
在item外面套一层mask,设置背景黑色。item设置opacity即可。
参考:css为图片添加一层蒙版_css给图片加一层蒙版-CSDN博客
html
<div class="item done">
<h2>Done</h2>
<div class="list">
<!-- 外面的阴影 -->
<div class="mask">
<div class="listItem">
<input type="checkbox">吃饭3
</div>
</div>
</div>
</div>
css
.done .listItem {
box-shadow: -5px 0 0 0 #999999;
opacity: 0.7;
}
.done .mask {
background: #000;
}
最终代码
html
<!-- todo-list.component.html -->
<header>
<section>
<label for="title">TodoList</label>
<input type="text" placeholder="添加ToDo">
</section>
</header>
<section>
<div class="item todo">
<h2>Todo</h2>
<div class="list">
<div class="listItem">
<input type="checkbox">吃饭1
</div>
<div class="listItem">
<input type="checkbox">睡觉1
</div>
<div class="listItem">
<input type="checkbox">喝水1
</div>
</div>
</div>
<div class="item doing">
<h2>Doing</h2>
<div class="list">
<div class="listItem">
<input type="checkbox">吃饭2
</div>
<div class="listItem">
<input type="checkbox">睡觉2
</div>
<div class="listItem">
<input type="checkbox">喝水2
</div>
</div>
</div>
<div class="item done">
<h2>Done</h2>
<div class="list">
<!-- 外面的阴影 -->
<div class="mask">
<div class="listItem">
<input type="checkbox" checked="checked">吃饭3
</div>
</div>
</div>
</div>
</section>
css
/* todo-list.component.css */
header {
height: 70px;
background-color: #333;
}
header section {
display: flex;
justify-content: space-between;
}
section {
margin: 0 auto;
width: 70vw;
}
header section label {
font-size: 28px;
color: #fff;
line-height: 70px;
}
header section input {
width: 35%;
margin: 10px 0;
padding-left: 15px;
border-radius: 10px;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.24), 0 1px 6px rgba(0, 0, 0, 0.45) inset;
}
.item {
margin: 20px 0;
}
.item h2 {
color: #000;
font-size: 28px;
font-weight: 700;
margin-bottom: 20px;
}
.item .listItem {
background-color: #dbdbdb;
margin: 15px 0;
height: 40px;
line-height: 40px;
font-size: 16px;
}
.todo .listItem {
box-shadow: -5px 0 0 0 #ede719;
}
.doing .listItem {
box-shadow: -5px 0 0 0 yellowgreen;
}
.done .listItem {
box-shadow: -5px 0 0 0 #999999;
opacity: 0.7;
}
.done .mask {
background: #000;
}
.item .listItem input[type=checkbox] {
width: 23px;
height: 23px;
/* 复选框与文字对齐 */
display: inline-block;
vertical-align: middle;
margin: 0 10px 2px;
}
功能(TS)
将输入框内容加入todoList(addTodo)
定义数据,写addTodo方法。
typescript
//todo-list.component.ts
export class TodoListComponent {
public todo: any = '' //在input栏,即将加入todoList
public todoList = [] as any;
public doingList = [] as any;
public doneList = [] as any;
// 添加代办时间到todo
addTodo(e: any) {
// 回车
if (e.keyCode == 13) {
this.todoList.push(this.todo)
this.todo = ''
}
}
}
在html中绑定数据和时间:
输入框:
html
<!-- todo-list.component.html -->
<header>
<section>
<label for="title">TodoList</label>
<input type="text" (keydown)="addTodo($event)" [(ngModel)]='todo' placeholder="添加ToDo">
</section>
</header>
todoList:
html
<div class="item todo">
<h2>Todo</h2>
<div class="list">
<div class="listItem" *ngFor="let item of todoList">
<input type="checkbox">{{item.todo}}
</div>
</div>
</div>
遇到的问题与解决:
写addTodo方法:
TypeScript 错误 property does not exist on type Object - 掘金 (juejin.cn)
Parameter 'xxx' implicitly has an 'any' type的解决_implicitly has an 'any' type-CSDN博客
在绑定[(ngModel)]='todo':解决Angular报错 Can't bind to 'ngModel' since it isn't a known property of 'input'-CSDN博客
将todoObj push进todoList:类型"{ name: any; value: string; }"的参数不能赋给类型"never"的参数。_类型"any"的参数不能赋给类型"never"的参数_干饭了干饭了1的博客-CSDN博客
将todo事件改到doing
功能:todo打勾(点击事件),它就加到doingList中。doing到done、done到todo以此类推。
typescript
// todo 改为doing
todoChange(key: any) {
this.doingList.push(this.todoList[key])
this.todoList.splice(key,1)
}
html
<div class="item todo">
<h2>Todo</h2>
<div class="list">
<div class="listItem" *ngFor="let item of todoList;let key=index">
<input type="checkbox" (click)="todoChange(key)">{{item}}
</div>
</div>
</div>
刷新一下,发现页面中的数据都没了。如果想要保存页面数据,我们需要做以下操作。
服务
参考:angularcli 第七篇(service 服务) - 撑死的喵~ - 博客园 (cnblogs.com)
在控制台创建服务:
ng g service services/storage
app.module.ts
中引入创建的服务:
在要使用的页面引入和注入服务:
具体服务:
可能的报错:ts报错:类型"string | null"的参数不能赋给类型"string"的参数。 不能将类型"null"分配给类型"string"。-CSDN博客
typescript
// storage.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class StorageService {
constructor() { }
setItem(key: any, value: any) {
localStorage.setItem(key, JSON.stringify(value));
}
getItem(key: any) {
return JSON.parse(localStorage.getItem(key) || '')
}
}
在每个会修改todoList、doingList、doneList的代码下面加上对应的this.storage.setItem('xx',this.xx)
,把数据存放在本地中。
typescript
// 添加代办时间到todo
addTodo(e: any) {
// 回车
if (e.keyCode == 13) {
this.todoList.push(this.todo)
this.todo = ''
this.storage.setItem('todoList',this.todoList)
}
}
// todo 改为doing
todoChange(key: any) {
this.doingList.push(this.todoList[key])
this.todoList.splice(key,1)
this.storage.setItem('todoList',this.todoList)
this.storage.setItem('doingList',this.doingList)
}
// doing 改为done
doingChange(key: any) {
this.doneList.push(this.doingList[key])
this.doingList.splice(key,1)
this.storage.setItem('doneList',this.doneList)
this.storage.setItem('doingList',this.doingList)
}
// done 改为todo
doneChange(key: any) {
this.todoList.push(this.doneList[key])
this.doneList.splice(key,1)
this.storage.setItem('todoList',this.todoList)
this.storage.setItem('doneList',this.doneList)
}
大功告成!
参考
angularjs - 和我一起入坑,Angular入门,Angular版的ToDoList - 个人文章 - SegmentFault 思否
box-shadow 设置单边、多边阴影 - 掘金 (juejin.cn)
css为图片添加一层蒙版_css给图片加一层蒙版-CSDN博客
TypeScript 错误 property does not exist on type Object - 掘金 (juejin.cn)
Parameter 'xxx' implicitly has an 'any' type的解决_implicitly has an 'any' type-CSDN博客
angularcli 第七篇(service 服务) - 撑死的喵~ - 博客园 (cnblogs.com)
ts报错:类型"string | null"的参数不能赋给类型"string"的参数。 不能将类型"null"分配给类型"string"。-CSDN博客