源码地址:https://github.com/BLKNjyty/reactstudy
前言,拿到项目直接npm install 会报错
这是因为之前有缓存,直接
npm cache clear --force
强制清除缓存在进行install
xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
包含了所有需要的配置(语法检查、jsx编译、devServer…)
下载好了所有相关的依赖
可以直接运行一个简单效果
react提供了一个用于创建react项目的脚手架库: create-react-app
项目的整体技术架构为: react + webpack + es6 + eslint
使用脚手架开发的项目的特点: 模块化, 组件化, 工程化
第一步,全局安装:npm i -g create-react-app
第二步,切换到想创项目的目录,使用命令:create-react-app hello-react
第三步,进入项目文件夹:cd hello-react
第四步,启动项目:npm start
public ---- 静态资源文件夹
favicon.icon ------ 网站页签图标
index.html **-------**主页面
logo192.png ------- logo图
logo512.png ------- logo图
manifest.json ----- 应用加壳的配置文件
robots.txt -------- 爬虫协议文件
src ---- 源码文件夹
App.css -------- App组件的样式
App.js--------App组件
App.test.js ---- 用于给App做测试
index.css ------ 样式
index.js ------入口文件
logo.svg ------- logo图
reportWebVitals.js
— 页面性能分析文件(需要web-vitals库的支持)
setupTests.js
---- 组件单元测试的文件(需要jest-dom库的支持)
拆分组件: 拆分界面,抽取组件
实现静态组件: 使用组件实现静态页面效果
实现动态组件
3.1动态显示初始化数据
3.1.1 数据类型
3.1.2 数据名称
3.1.2 保存在哪个组件?
3.2 交互(从绑定事件监听开始)
此案例不涉及css的编写,直接使用教程提供的css样式
界面分为header,list,item和footer四部分。
其中head是头部的输入框,item是每一个代办事项,list是item的集合展示,foot是最下面的全选、删除所选等功能。
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}
]
}
render(){
return (
<div className="todo-container">
<div className="todo-warp">
<Header/>
<List todos={todos}/>
<Footer todos={todos}/>
</div>
</div>
)
}
}
export default class Header extends Component{
render(){
return(
<div className="todo-header">
<input type="text" placeholder="请输入你的任务名称,按回车键确定">
</div>
)
}
}
export default class List extends Component{
render(){
const {todos}=this.props
return(
<ul className="todo-main">
{
todos.map(todo=>{
return <Item key={todo.id} {...todo}>
}
)
}
</ul>
)
}
}
export default Item extends Component{
render(){
const {id,name,done}=this.props
return(
<li>
<label>
<input type="checkbox" checked={done}>
<span>name</span>
</label>
<button className="btn btn-danger">删除</buttton>
</li>
)
}
}
export default class Footer extends Component{
render(){
const {todos}=this.props
return(
<div className="todo-footer">
<label>
<input type="checkbox"/ checked=true>
</label>
<span>
<span>已完成{xxx}</span>/全部{xxx}
</span>
<button className="btn btn-danger">清楚已完成任务</button>
</div>
)
}
}
export default Item extends Component{
state={mouse:false}
//添加鼠标移出、移出的item框效果
handleMouse=(flag)=>{
return ()=>{
this.setState({mouse:flag})
}
}
//TODO的内容在父组件APP里面,子孙组件删除父组件的内容,可以使用父组件传递给子组件的函数(APP-list-item)
handleDelete=(id)=>{
if(window.confirm('确定删除吗?')){
this.props.deleteTodo(id)
}
}
//勾选或者取消勾选的时候,done值跟随改变
handleCheck=(id)=>{
return (event)=>{
this.props.updateTodo(id,event.target.checked)
}
}
render(){
const {id,name,done}=this.props
return(
<li style={{background: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" display:mouse?'block':'none'>删除</buttton>
</li>
)
}
}
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}
]
}
//删除具体某个item
deleteTodo=(id)=>{
const {todos}=this.state
const newTodos = todos.filter((todo)=>{
return todo.id!==id
}
)
this.setState({todos:newTodos})
}
//更新一个item的状态
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})
}
render(){
return (
<div className="todo-container">
<div className="todo-warp">
<Header/>
<List todos={todos} updateTodo={this.updateTodo} deleteTodo={this.deleteTodo}/>
<Footer todos={todos}/>
</div>
</div>
)
}
}
export default class List extends Component{
render(){
const {todos,deleteTodo,updateTodo}=this.props
return(
<ul className="todo-main">
{
todos.map(todo=>{
return <Item key={todo.id} {...todo} updateTodo={updateTodo} deleteTodo={deleteTodo} >
}
)
}
</ul>
)
}
}
export default class Header extends Component{
handleKeyUp=(event)=>{
const {keyCode,target}=event
if(keyCode!=13)return
if(target.value.trim(0=)==''){
alert("输入不能为空")
return
}
const todoObj={id:nanoid(),name:target,done:false}
//同上,子组件想传递信息给父组件,调用父组件传递给子组件的函数即可
this.props.addTodo(todoObj)
target.value=''
}
render(){
return(
<div className="todo-header">
<input onKeyUp={this.handleKeyUp} type="text" placeholder="请输入你的任务名称,按回车键确定">
</div>
)
}
}
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}
]
}
//删除具体某个item
deleteTodo=(id)=>{
const {todos}=this.state
const newTodos = todos.filter((todo)=>{
return todo.id!==id
}
)
this.setState({todos:newTodos})
}
//添加一个item
addTodo=(todoObj)=>{
const {todos}=this.state
const newTodos=[todoObj,...todos]
this.setState({todos:newTodos})
}
//updateTodo用于更新一个todo对象
updateTodo = (id,done)=>{
//获取状态中的todos
const {todos} = this.state
//匹配处理数据--id一样则复制一个并替换其中的done属性,如果id不一样则直接返回
const newTodos = todos.map((todoObj)=>{
if(todoObj.id === id) return {...todoObj,done}
else return todoObj
})
this.setState({todos:newTodos})
}
render(){
return (
<div className="todo-container">
<div className="todo-warp">
<Header addTodo={this.addTodo}/>
<List todos={todos} deleteTodo={this.deleteTodo} updateTodo={this.updateTodo}/>
<Footer todos={todos}/>
</div>
</div>
)
}
}
export default class Footer extends Component{
//将父组件的item的done全部变为true或者false
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=true>
</label>
<span>
<span>已完成{doneCount}</span>/全部{total}
</span>
<button onClick={this.handleClearAllDone} className="btn btn-danger" >清楚已完成任务</button>
</div>
)
}
}
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}
]
}
//删除具体某个item
deleteTodo=(id)=>{
const {todos}=this.state
const newTodos = todos.filter((todo)=>{
return todo.id!==id
}
)
this.setState({todos:newTodos})
}
//添加一个item
addTodo=(todoObj)=>{
const {todos}=this.state
const newTodos=[todoObj,...todos]
this.setState({todos:newTodos})
}
//updateTodo用于更新一个todo对象
updateTodo = (id,done)=>{
//获取状态中的todos
const {todos} = this.state
//匹配处理数据--id一样则复制一个并替换其中的done属性,如果id不一样则直接返回
const newTodos = todos.map((todoObj)=>{
if(todoObj.id === id) return {...todoObj,done}
else return todoObj
})
this.setState({todos:newTodos})
}
//全选、全不选
checkAllTodo=(done)=>{
const {todos}=this.state
const newTodos=todos.map((todoObj)=>{
return {...obj,done}
}
)
this.setState({todos:newTodos})
}
//清除所有已完成的任务
clearAllDone=()=>{
const {todos}=this.state
const newTodos=todos.filter((todoObj)=>{
return !todoObj.done
}
)
this.setState({todos:newTodos})
}
render(){
return (
<div className="todo-container">
<div className="todo-warp">
<Header addTodo={this.addTodo}/>
<List todos={todos} deleteTodo={this.deleteTodo} updateTodo={this.updateTodo}/>
<Footer todos={todos} checkAllTodo={this.checkAllTodo} clearAllDone={this.clearAllDone}/>
</div>
</div>
)
}
}
声明,本文内容参考b 站 尚硅谷视频。链接