• React 全栈体系(六)


    第三章:React 应用(基于 React 脚手架)

    二、组件的组合使用 - TodoList

    3. 添加 todo

    3.1 App
    /* src/App.jsx */
    //创建“外壳”组件App
    import React,{Component} from 'react'
    import Header from './components/Header'
    import List from './components/List'
    import Footer from './components/Footer'
    import './App.css'
    
    //创建并暴露App组件
    export default class App extends Component{
    
    	//初始化状态
    	state = {todos:[
    		{id:'001',name:'吃饭',done:true},
    		{id:'002',name:'睡觉',done:true},
    		{id:'003',name:'打代码',done:false},
    		{id:'004',name:'逛街',done:false}
    	]}
    
    	//addTodo用于添加一个todo,接收的参数是todo对象
    	addTodo = (todoObj) => {
    		//获取原todos
    		const {todos} = this.state
    		//追加一个todo
    		const newTodos = [todoObj,...todos]
    		//更新状态
    		this.setState({todos:newTodos})
    	}
    	render(){
    		const {todos} = this.state
    		return (
    			<div className="todo-container">
    				<div className="todo-wrap">
    					<Header addTodo={this.addTodo}/>
    					<List todos={todos}/>
    					<Footer />
    				</div>
    			</div>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    3.2 Header
    /* src/components/Header/index.jsx */
    import React, { Component } from 'react'
    import {nanoid} from 'nanoid'
    import './index.css'
    
    
    export default class Header extends Component {
    
      handleKeyUp = (event) => {
        //解构赋值获取keyCode,target
        const {keyCode, target} = event
        //判断是否是回车按键
        if(event.keyCode !== 13) return
        //添加的todo名字不能为空
    	if(target.value.trim() === ''){
    		alert('输入不能为空')
    		return
    	}
        //准备好一个todo对象
        const todoObj = {id:nanoid(), name:target.value, done:false}
        //将todoObj传递给App
        this.props.addTodo(todoObj)
        //清空输入
    	target.value = ''
      }
      render() {
        return (
            <div className="todo-header">
                <input onKeyUp={this.handleKeyUp} type="text" placeholder="请输入你的任务名称,按回车键确认"/>
            </div>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    4. 鼠标移入效果

    Item
    /* src/components/Item/index.jsx */
    import React, { Component } from 'react'
    import './index.css'
    
    export default class Item extends Component {
      state = {mouse:false} //标识鼠标移入、移出
    
      //鼠标移入、移出的回调
    	handleMouse = (flag)=>{
    		return ()=>{
    			this.setState({mouse:flag})
    		}
    	}
    
      render() {
        const {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" defaultChecked={done}/>
                <span>{name}</span>
            </label>
            <button className="btn btn-danger" style={{display:mouse?'block':'none'}}>删除</button>
            </li>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    5. 添加一个 todo

    5.1 App
    /* src/App.jsx */
    //创建“外壳”组件App
    import React,{Component} from 'react'
    import Header from './components/Header'
    import List from './components/List'
    import Footer from './components/Footer'
    import './App.css'
    
    //创建并暴露App组件
    export default class App extends Component{
    	//状态在哪里,操作状态的方法就在哪里
    
    	//初始化状态
    	state = {todos:[
    		{id:'001',name:'吃饭',done:true},
    		{id:'002',name:'睡觉',done:true},
    		{id:'003',name:'打代码',done:false},
    		{id:'004',name:'逛街',done:false}
    	]}
    
    	//addTodo用于添加一个todo,接收的参数是todo对象
    	addTodo = (todoObj) => {
    		//获取原todos
    		const {todos} = this.state
    		//追加一个todo
    		const newTodos = [todoObj,...todos]
    		//更新状态
    		this.setState({todos:newTodos})
    	}
    
    	//updateTodo用于更新一个todo对象
    	updateTodo = (id,done)=>{
    		//获取状态中的todos
    		const {todos} = this.state
    		//匹配处理数据
    		const newTodos = todos.map((todoObj)=>{
    			if(todoObj.id === id) return {...todoObj,done}
    			else return todoObj
    		})
    		this.setState({todos:newTodos})
    	}
    
    	render(){
    		const {todos} = this.state
    		return (
    			<div className="todo-container">
    				<div className="todo-wrap">
    					<Header addTodo={this.addTodo}/>
    					<List todos={todos} updateTodo={this.updateTodo}/>
    					<Footer />
    				</div>
    			</div>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    5.2 List
    /* src/components/List/index.jsx */
    import React, { Component } from 'react'
    import Item from '../Item'
    import './index.css'
    
    export default class List extends Component {
      render() {
        const {todos,updateTodo} = this.props
        return (
            <ul className="todo-main">
              {
                todos.map(todo=> {
                  return <Item key={todo.id} {...todo} updateTodo={updateTodo}/>
                })
              }
            </ul>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    5.3 Item
    /* src/components/Item/index.jsx */
    import React, { Component } from 'react'
    import './index.css'
    
    export default class Item extends Component {
      state = {mouse:false} //标识鼠标移入、移出
    
      //鼠标移入、移出的回调
    	handleMouse = (flag)=>{
    		return ()=>{
    			this.setState({mouse:flag})
    		}
    	}
    
      //勾选、取消勾选某一个todo的回调
    	handleCheck = (id)=>{
    		return (event)=>{
    			this.props.updateTodo(id,event.target.checked)
    		}
    	}
    
      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" defaultChecked={done} onChange={this.handleCheck(id)}/>
                <span>{name}</span>
            </label>
            <button className="btn btn-danger" style={{display:mouse?'block':'none'}}>删除</button>
            </li>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    6. 对 props 进行限制

    6.1 Header
    /* src/components/Header/index.jsx */
    import React, { Component } from 'react'
    import PropTypes from 'prop-types'
    import {nanoid} from 'nanoid'
    import './index.css'
    
    
    export default class Header extends Component {
    
      //对接收的props进行:类型、必要性的限制
    	static propTypes = {
    		addTodo:PropTypes.func.isRequired
    	}
    
      //键盘事件的回调
      handleKeyUp = (event) => {
        //解构赋值获取keyCode,target
        const {keyCode, target} = event
        //判断是否是回车按键
        if(event.keyCode !== 13) return
        //添加的todo名字不能为空
    		if(target.value.trim() === ''){
    			alert('输入不能为空')
    			return
    		}
        //准备好一个todo对象
        const todoObj = {id:nanoid(), name:target.value, done:false}
        //将todoObj传递给App
        this.props.addTodo(todoObj)
        //清空输入
    		target.value = ''
      }
      render() {
        return (
            <div className="todo-header">
                <input onKeyUp={this.handleKeyUp} type="text" placeholder="请输入你的任务名称,按回车键确认"/>
            </div>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    6.2 List
    /* src/components/List/index.jsx */
    import React, { Component } from 'react'
    import PropTypes from 'prop-types'
    import Item from '../Item'
    import './index.css'
    
    export default class List extends Component {
      //对接收的props进行:类型、必要性的限制
    	static propTypes = {
    		todos:PropTypes.array.isRequired,
    		updateTodo:PropTypes.func.isRequired
    	}
    
      render() {
        const {todos,updateTodo} = this.props
        return (
            <ul className="todo-main">
              {
                todos.map(todo=> {
                  return <Item key={todo.id} {...todo} updateTodo={updateTodo}/>
                })
              }
            </ul>
        )
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    7. 删除一个 todo

    7.1 App
    /* src/App.jsx */
    //创建“外壳”组件App
    import React,{Component} from 'react'
    import Header from './components/Header'
    import List from './components/List'
    import Footer from './components/Footer'
    import './App.css'
    
    //创建并暴露App组件
    export default class App extends Component{
    	//状态在哪里,操作状态的方法就在哪里
    
    	//初始化状态
    	state = {todos:[
    		{id:'001',name:'吃饭',done:true},
    		{id:'002',name:'睡觉',done:true},
    		{id:'003',name:'打代码',done:false},
    		{id:'004',name:'逛街',done:false}
    	]}
    
    	//addTodo用于添加一个todo,接收的参数是todo对象
    	addTodo = (todoObj) => {
    		//获取原todos
    		const {todos} = this.state
    		//追加一个todo
    		const newTodos = [todoObj,...todos]
    		//更新状态
    		this.setState({todos:newTodos})
    	}
    
    	//updateTodo用于更新一个todo对象
    	updateTodo = (id,done)=>{
    		//获取状态中的todos
    		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)=>{
    		//获取原来的todos
    		const {todos} = this.state
    		//删除指定id的todo对象
    		const newTodos = todos.filter((todoObj)=>{
    			return todoObj.id !== id
    		})
    		//更新状态
    		this.setState({todos:newTodos})
    	}
    
    	render(){
    		const {todos} = this.state
    		return (
    			<div className="todo-container">
    				<div className="todo-wrap">
    					<Header addTodo={this.addTodo}/>
    					<List todos={todos} updateTodo={this.updateTodo} deleteTodo={this.deleteTodo}/>
    					<Footer />
    				</div>
    			</div>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    7.2 List
    /* src/components/List/index.jsx */
    import React, { Component } from 'react'
    import PropTypes from 'prop-types'
    import Item from '../Item'
    import './index.css'
    
    export default 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 <Item key={todo.id} {...todo} updateTodo={updateTodo} deleteTodo={deleteTodo}/>
    	            })
    	          }
    	        </ul>
    	    )
      	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    7.3 Item
    /* src/components/Item/index.jsx */
    import React, { Component } from 'react'
    import './index.css'
    
    export default class Item extends Component {
        state = {mouse:false} //标识鼠标移入、移出
    
        //鼠标移入、移出的回调
    	handleMouse = (flag)=>{
    		return ()=>{
    			this.setState({mouse:flag})
    		}
    	}
    
        //勾选、取消勾选某一个todo的回调
    	handleCheck = (id)=>{
    		return (event)=>{
    			this.props.updateTodo(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" defaultChecked={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>
    	    )
     	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    8. 实现底部功能

    8.1 App
    /* src/App.jsx */
    import React, { Component } from 'react'
    import Header from './components/Header'
    import List from './components/List'
    import Footer from './components/Footer'
    import './App.css'
    
    export default class App extends Component {
    	//状态在哪里,操作状态的方法就在哪里
    
    	//初始化状态
    	state = {todos:[
    		{id:'001',name:'吃饭',done:true},
    		{id:'002',name:'睡觉',done:true},
    		{id:'003',name:'打代码',done:false},
    		{id:'004',name:'逛街',done:false}
    	]}
    
    	//addTodo用于添加一个todo,接收的参数是todo对象
    	addTodo = (todoObj)=>{
    		//获取原todos
    		const {todos} = this.state
    		//追加一个todo
    		const newTodos = [todoObj,...todos]
    		//更新状态
    		this.setState({todos:newTodos})
    	}
    
    	//updateTodo用于更新一个todo对象
    	updateTodo = (id,done)=>{
    		//获取状态中的todos
    		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)=>{
    		//获取原来的todos
    		const {todos} = this.state
    		//删除指定id的todo对象
    		const newTodos = todos.filter((todoObj)=>{
    			return todoObj.id !== id
    		})
    		//更新状态
    		this.setState({todos:newTodos})
    	}
    
    	//checkAllTodo用于全选
    	checkAllTodo = (done)=>{
    		//获取原来的todos
    		const {todos} = this.state
    		//加工数据
    		const newTodos = todos.map((todoObj)=>{
    			return {...todoObj,done}
    		})
    		//更新状态
    		this.setState({todos:newTodos})
    	}
    
    	//clearAllDone用于清除所有已完成的
    	clearAllDone = ()=>{
    		//获取原来的todos
    		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">
    					<Header addTodo={this.addTodo}/>
    					<List todos={todos} updateTodo={this.updateTodo} deleteTodo={this.deleteTodo}/>
    					<Footer todos={todos} checkAllTodo={this.checkAllTodo} clearAllDone={this.clearAllDone}/>
    				</div>
    			</div>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    8.2 Header
    /* src/components/Header/index.jsx */
    import React, { Component } from 'react'
    import PropTypes from 'prop-types'
    import {nanoid} from 'nanoid'
    import './index.css'
    
    export default class Header extends Component {
    
    	//对接收的props进行:类型、必要性的限制
    	static propTypes = {
    		addTodo:PropTypes.func.isRequired
    	}
    
    	//键盘事件的回调
    	handleKeyUp = (event)=>{
    		//解构赋值获取keyCode,target
    		const {keyCode,target} = event
    		//判断是否是回车按键
    		if(keyCode !== 13) return
    		//添加的todo名字不能为空
    		if(target.value.trim() === ''){
    			alert('输入不能为空')
    			return
    		}
    		//准备好一个todo对象
    		const todoObj = {id:nanoid(),name:target.value,done:false}
    		//将todoObj传递给App
    		this.props.addTodo(todoObj)
    		//清空输入
    		target.value = ''
    	}
    
    	render() {
    		return (
    			<div className="todo-header">
    				<input onKeyUp={this.handleKeyUp} type="text" placeholder="请输入你的任务名称,按回车键确认"/>
    			</div>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    8.3 List
    /* src/components/List/index.jsx */
    import React, { Component } from 'react'
    import PropTypes from 'prop-types'
    import Item from '../Item'
    import './index.css'
    
    export default 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 <Item key={todo.id} {...todo} updateTodo={updateTodo} deleteTodo={deleteTodo}/>
    					})
    				}
    			</ul>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    8.4 Item
    /* src/components/Item/index.jsx */
    import React, { Component } from 'react'
    import './index.css'
    
    export default class Item extends Component {
    
    	state = {mouse:false} //标识鼠标移入、移出
    
    	//鼠标移入、移出的回调
    	handleMouse = (flag)=>{
    		return ()=>{
    			this.setState({mouse:flag})
    		}
    	}
    
    	//勾选、取消勾选某一个todo的回调
    	handleCheck = (id)=>{
    		return (event)=>{
    			this.props.updateTodo(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>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    8.5 Footer
    /* src/components/Footer/index.jsx */
    import React, { Component } from 'react'
    import './index.css'
    
    export default class Footer extends Component {
    
    	//全选checkbox的回调
    	handleCheckAll = (event)=>{
    		this.props.checkAllTodo(event.target.checked)
    	}
    
    	//清除已完成任务的回调
    	handleClearAllDone = ()=>{
    		this.props.clearAllDone()
    	}
    
    	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 type="checkbox" onChange={this.handleCheckAll} checked={doneCount === total && total !== 0 ? true : false}/>
    				</label>
    				<span>
    					<span>已完成{doneCount}</span> / 全部{total}
    				</span>
    				<button onClick={this.handleClearAllDone} className="btn btn-danger">清除已完成任务</button>
    			</div>
    		)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    三、总结

    1.拆分组件、实现静态组件,注意:className、style的写法
    2.动态初始化列表,如何确定将数据放在哪个组件的state中?
    			——某个组件使用:放在其自身的state中
    			——某些组件使用:放在他们共同的父组件state中(官方称此操作为:状态提升)
    3.关于父子之间通信:
    		1.【父组件】给【子组件】传递数据:通过props传递
    		2.【子组件】给【父组件】传递数据:通过props传递,要求父提前给子传递一个函数
    4.注意defaultChecked 和 checked的区别,类似的还有:defaultValue 和 value
    5.状态在哪里,操作状态的方法就在哪里
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    java中锁的面试题
    游戏陪玩系统app
    【斗破年番】火火抱彩鳞把她整害羞啦!女王解锁新造型,身形丰满超有料
    【Vue-Element-UI -el-tree数据格式与组件中的格式不一样】
    【假设检验】MATLAB实现K-S检验
    金仓数据库KingbaseES物理备份恢复命令选项(stanza-delete命令)
    python导出csv文件进mysql
    2023贵州师范大学计算机考研信息汇总
    JUC第六讲:ThreadLocal/InheritableThreadLocal详解
    Windows字符和字符串处理
  • 原文地址:https://blog.csdn.net/sgsgkxkx/article/details/132864655