TS + React 实现 todos添加任务
展示任务列表
1.为父组件app,提供状态(任务列表数据)和类型
//父组件传递数据
import { Component } from 'react'
import TodoList from './components/TodoList'
//任务项的类型
type TodoItem={id:number;text:string;done:boolean}
//app组件的状态类型
type Todos={ todos:TodoItem[]}
const todos:TodoItem[] = [
{ id: 1, text: '吃饭', done: true},
{ id: 2, text: '休息',done: false}
]
//通过泛型为组件提供状态类型
export default class App extends Component<{},Todos> {
state:Todos={todos}
render() {
const {todos}=this.state
return (<TodoList list={todos} />)
}
}
2.为子组件TodoList 指定能够接收到的props类型
//在list子组件指定类型
import React from 'react'
//任务项的类型
type TodoItem={id:number;text:string;done:boolean}
//提供props类型
interface Props{
list:TodoItem[]
}
//通过泛型为组件提供属性类型
export default class TodoList extends React.Component<Props> {
render() {
const {list}=this.props
return (
<ul className="todo-list">
{/* 编辑样式:editing 已完成样式:completed */}
{
list.map(p=>{
return(
<li key={p.id} className={p.done?'completed':''}>
<div className="view">
<input className="toggle" type="checkbox" />
<label>{p.text}</label>
<button className="destroy" />
</div>
<input className="edit" defaultValue="Create a TodoMVC template" />
</li>
)
})
}
</ul>
)
}
}
3.将任务列表数据传递给TodoList组件
//父组件传递数据
<TodoList list={todos} />
## 使用类型声明文件复用类型
### 1.创建todos.d.ts文件、将公共的类型移动到todos.d.ts文件中、并暴露
//todos.d.ts
//任务项的类型
export type TodoItem = { id: number; text: string; done: boolean }
2.在用到该类型的组件中导入
//app父组件中导入TodoItem类型
import { TodoItem} from './todos'
//TodoList子组件中导入TodoItem类型
import { TodoItem} from '../todos''
添加任务
思路:子组件获取到文本框的值、通过子->父通讯将值传递给父组件、然后,在父组件将任务添加到状态数据中
1.为子组件添加状态和属性及类型
//添加属性的类型
type Props={ onAddTodo:(text:string)=>void}
//状态的类型
type State={
text:string
}
//通过泛型为子组件提供状态、属性类型
class TodoAdd extends React.Component<Props,State> {
}
{/* 父组件传递函数 */}
<TodoAdd onAddTodo={text=>{}} />
2.通过受控组件方式获取到文本框的值
//指定输入类型
onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
//获取文本框的值
this.setState({ text: e.target.value })
}
<input className="new-todo" placeholder="What needs to be done?"
autoFocus
value={text}
onChange={this.onChange}
onKeyDown={this.onAdd}
/>
3. 在子组件文本框按下回车传递数据给父组件
//指定函数类型、触发父亲组件方法
onAdd = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.code === "Enter")
this.props.onAddTodo(this.state.text)
}
<input className="new-todo" placeholder="What needs to be done?"
autoFocus
value={text}
onChange={this.onChange}
onKeyDown={this.onAdd}
/>
4. 父组件接收子组件传递过来的数据、添加数据
//子组件调用父组件的方法传递参数、在父组件方法中接收值
addTodo=(text:string)=>{
const {todos}=this.state
const id=todos.length===0?1:todos[todos.length-1].id+1
//接收子组件传递的参数
this.setState({
todos:[...todos,{id,text,done:false}]
})
}