一.自动化生成react基本框架
创建react脚手架项目 直接用 npx create-react-app aa(aa为自己的项目名称) 命令
等待软件下载好基础包后,输入cd aa(转到所创项目名) 命令,npm start 命令启动服务,可以看见自动生成跳转到一个react展示页面
二.更改App.js等内容实现功能
App.js文件
import Header from "./header/header"; import List from "./list/list"; import Footer from "./footer/footer"; import React from "react"; export default class App extends React.***ponent{ //初始化状态 state ={todos: [ {id:'001',name:'吃饭',done:true}, {id:'002',name:'睡觉',done:false}, {id:'003',name:'打代码',done:true}, ]} //addTodo用于添加一个todo,接收的参数是todo对象 addTodo=(todoObj)=>{ //获取原todos const {todos}=this.state //追加一个todos const newTodos=[todoObj,...todos] //更新状态 this.setState({todos: newTodos}) } //用于更新一个todo对象 updateTodo=(id,done)=>{ // 获取状态中的todos const {todos}=this.state //匹配处理数据 const newTodos=todos.map((todoObj)=>{ if (todoObj.id ===id)return{...todoObj,done:done} else return todoObj }) this.setState({todos:newTodos}) } //用于删除一个todo对象 deleteTodo=(id)=>{ //获取原来的todos const {todos}=this.state //删除指定id的todo对象 const newTodos=todos.filter((todoObj)=>{ return todoObj.id!==id }) //更新状态 this.setState({todos: newTodos}) } //用于全选 checkAllTodo=(done)=>{ //获取原来的todos const {todos}=this.state //加工数据 const newTodos=todos.map((todoObj)=>{ return{...todoObj,done} }) //更新状态 this.setState({todos: newTodos}) } //清除所用已完成的任务 clearAllDone = ()=>{ //获取原来的todos const {todos}=this.state //过滤数据 const newTodos=todos.filter((todoObj)=>{ return todoObj.done === false }) 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> ); } }
Header.js文件
import React from "react"; import PropTypes from "prop-types"; import {nanoid} from "nanoid"; export default class Header extends React.***ponent { //对接收的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> ); } }
List.js文件
import React from "react"; import Item from "../item/item"; import PropTypes from "prop-types"; export default class List extends React.***ponent { //对接收的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> ); } }
Item.js文件
import React from "react"; import "./Item.css" export default class Item extends React.***ponent { //标识鼠标移入、移出 state={mouse:false} //勾选或取消勾选某一个toso的回调函数 handleCheck=(id)=>{ return(event)=>{ this.props.updateTodo(id,event.target.checked) } } //删除某一个toso的回调函数 handleDelete=(id)=>{ if (window.confirm('确定删除吗?')){ this.props.deleteTodo(id) } } //鼠标移入、移出的回调函数 handleMouse =(flag)=>{ return()=>{ this.setState({mouse:flag}) } } render() { const {id,name,done}=this.props const {mouse}=this.state return ( <li style={{backgroundColor:mouse?'#ddd':'white'}} onMouseLeave={this.handleMouse(false)} onMouseEnter={this.handleMouse(true)}> <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.js文件
import React from "react"; export default class Fooder extends React.***ponent { //全选checkcbox的回调 handleCheckAll=(event)=>{ this.props.checkAllTodo(event.target.checked) } //清除所用已完成的任务 handleClearAllDone =()=>{ this.props.clearAllDone() } render() { const {todos}=this.props //已完成的个数 const doneCount=todos.reduce((pre,current)=>{return pre+(current.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> ); } }
最终实现效果如下图所示:
如果想改变样式,需引入css文件,对布局进行进一步处理
了解详细原理请参考以下链接
【尚硅谷React教程(已加更新版内容,B站最火)】 https://www.bilibili.***/video/BV1wy4y1D7JT/?p=56&share_source=copy_web&vd_source=db9c6d25ddec3a6c8b592f58d4d29cd9