1.Tolist案例(父子传参实现增删改)

目录结构

实现效果:

App.jsx

class App extends Component {
// 状态在哪里, 操作状态的方法就在哪里
state = {
todos:[
{id:1, name:'吃饭', done: true},
{id:2, name:'睡觉', done: true},
{id:3, name:'打代码', done: false},
{id:4, name:'光街', done: true},
]
} // addTodo用于添加一个todo, 接收的参数是todo对象
addTodo = (todoObj) =>{
const {todos} = this.state
const newTodos = [todoObj, ...todos]
this.setState({todos:newTodos})
} // updateTodo用于更新一个todo对象
updateTodo = (id, done) => {
const {todos} = this.state
const newTodos = todos.map(todoObj=>{
if (todoObj.id === id) return {...todoObj, done}
else return todoObj
})
this.setState({todos:newTodos})
} // deleteTodo用于删除一个todo对象
deleteTodo = (id) => {
const {todos} = this.state
const newTodos = todos.filter((todoObj)=>{
// 将id不是要删除的todo,重新过滤到一个新数组
return todoObj.id !== id
})
this.setState({
todos:newTodos
})
}
//checkAllTodo用于全选或者取消全选
checkAllTodo = (done) => {
const {todos} = this.state
const newTodos = todos.map((todoObj)=>{
return {...todoObj, done}
})
this.setState({
todos:newTodos
})
} // 删除已完成的任务(done为true,删除已选中的,批量删除)
clearAllDone = () => {
const {todos} = this.state
const newTodos = todos.filter(todoObj => {
return !todoObj.done
})
this.setState({
todos: newTodos
})
} render() {
const {todos} = this.state
return (
<div className="todo-container">
<div className="todo-wrap">
{/* 子传父 通过子调用父函数 传参 */}
<Headers addTodo={this.addTodo}/>
{/* 父传子 传参 */}
<List todos={todos} updateTodo={this.updateTodo} deleteTodo={this.deleteTodo}/>
<Footer todos={todos} checkAllTodo={this.checkAllTodo} clearAllDone={this.clearAllDone}/>
</div>
</div> )
}
}

Headers.jsx

class Headers extends Component{

    //对接收的props进行:类型、必要性的限制
static propTypes = {
addTodo:PropTypes.func.isRequired
} // 键盘回车事件, 13是回车返回的唯一值
handleKeyUp = (event) => {
const {keyCode, target} = event
if (keyCode !== 13 || target.value.trim() === '') return
const todoObj = {id:nanoid(), name:target.value, done:false}
// 调用父组件函数,添加一个todoObj
this.props.addTodo(todoObj)
// 清空输入框
target.value = ''
// console.log(event.target.value, event.keyCode) } render() {
return (
<div className="todo-header">
{/*监听键盘事件*/}
<input onKeyUp={this.handleKeyUp} type="text" placeholder="请输入你的任务名称,按回车键确认"/>
</div>
)
}
}

List.jsx

class List extends Component{

    // 对接收的props进行类型、必要性限制
static propTypes = {
todos: PropTypes.array.isRequired,
updateTodo: PropTypes.func.isRequired,
deleteTodo: PropTypes.func.isRequired, } render() {
// 接收从父组件传来的数组和方法
const {todos, updateTodo, deleteTodo} = this.props
return (
<ul className="todo-main">
{
todos.map(todo => {
return <Items key={todo.id} {...todo} updateTodo={updateTodo} deleteTodo={deleteTodo}/>
})
} </ul>
)
}
}

Items.jsx

class Items extends Component {

    state = {mouse:false}  // 标识鼠标移入、移出

    //鼠标移入、移除的回调
handleMouse = (flag) =>{
// 函数柯里化
return () =>{
this.setState({mouse:flag})
}
} // 勾选、取消勾选某一个todo的回调
handleCheck = (id) => {
return (event)=>{
this.props.updateTodo(id, event.target.checked)
// console.log(id, event.target.checked)
} } // 删除一个todo的回调
handleDelete = (id) =>{
if (window.confirm('确实删除?'))
this.props.deleteTodo(id)
} render() {
const {id, name, done} = this.props
const {mouse} = this.state
return (
<li style={{backgroundColor:mouse ? '#ddd': 'white'}} onMouseEnter={this.handleMouse(true)} onMouseLeave={this.handleMouse(false)}>
<label>
<input type="checkbox" checked={done} onChange={this.handleCheck(id)}/>
<span>{name}</span>
</label>
<button onClick={()=>this.handleDelete(id)} className="btn btn-danger" style={{display: mouse? 'block': 'none'}}>删除</button>
</li>
)
}
}

Footer.jsx

class Footer extends Component{

    handleCheckAll = (event) => {
// 是否全选或者取消选中
const done = event.target.checked
this.props.checkAllTodo(done)
} render() {
const {todos} = this.props
// 已完成的个数
const doneCount = todos.reduce((pre, todo)=>pre+(todo.done? 1 : 0),0)
// 总数
const total = todos.length return (
<div className="todo-footer">
<label>
<input onChange={this.handleCheckAll} type="checkbox" checked={doneCount === total && total !== 0}/>
</label>
<span><span>已完成{doneCount}</span> / 全部{total}</span>
<button onClick={this.props.clearAllDone} className="btn btn-danger">清除已完成任务</button>
</div>
)
}
}

最新文章

  1. python 获取一个列表有多少连续列表
  2. Sublime Text 3汉化中文版
  3. CRM HomePage.aspx
  4. javasE学习笔记:关键字super的使用
  5. LoadRunner用户行为模拟器 《第三篇》
  6. 搭建高性能计算环境(八)、应用软件的安装之gromacs
  7. Dijkstra算法亲自实践
  8. BZOJ 1803 Query on a tree III
  9. BZOJ 2005 能量采集(容斥原理)
  10. apache启动报错(98)Address already in use: make_sock: could not bind to...
  11. 【原创】OllyDBG 入门系列(一)-认识OllyDBG
  12. iOS上绘制自然的签名-b
  13. matlab遗传算法
  14. NFine常见错误
  15. java并发之可见性与原子性:Syncronized和volatile
  16. js面向对象自定义MyString()的构造器函数,实现内建String()属性和方法:
  17. 使用docker试用各种软件及docker-ES设置
  18. Python_Mix*OS模块,序列化模块种的json,pickle
  19. SparkML之推荐引擎(二)---推荐模型评估
  20. 【对比分析四】position的absolute与fixed共同点与不同点

热门文章

  1. Cesium加载地形数据只显示半个地球
  2. 《手把手教你》系列技巧篇(十一)-java+ selenium自动化测试-元素定位大法之By tag name(详细教程)
  3. maven 工程构建 之_____&lt;dependencyManagement&gt;标签
  4. videojs文档翻译-SeekBar
  5. 从零开始了解kubernetes
  6. shiro反序列化550、721
  7. 终于彻底搞清楚了spin-lock 之一次CPU问题定位过程总结
  8. 大龄程序员的出路在哪里?八年老Android的一点心得
  9. 物理机安装ESXi并优化部署虚拟机
  10. Docker部署Mysql实践