作为React入门教程,todoList经常被哪来做入门教程,今天我们也来手把手搭建个todolist,简单粗暴,方便学习
1:脚手架搭建一个项目react-study
create-react-app react-study
2:进入目录,启动项目
cd react-study
npm start
3:新建一个TodoList.js
import React,{Component,Fragment} from 'react';
import './App.css';
import TodoItem from './TodoItem'
class TodoList extends Component{
constructor(props) {
super(props);
this.state={
value:'',
list:[]
}
}
render(){
return(
<Fragment>
<label htmlFor="username">用户名:</label>
<input type='text' id="username" className='input' value={this.state.value}
onChange={this.changeValue}
/><button onClick={this.submitHandle}>提交</button>
<ul>
{
this.state.list.map((item,index)=>{
return (
<div key={index}>
<TodoItem content={item} index={index}
deleteOne={this.deleteOne}
/>
{/* 注意这里有个坑,子组件TodoItem明明加了key一直报错,是因为要加到父级div上面才可以
<li onClick={this.remove}
>
{this.props.content}
</li>
*/}
</div>
)
})
}
</ul>
</Fragment>
)
}
//input 改变
changeValue=(e)=>{
let v =e.target.value;
this.setState({
value:v
})
}
//新增
submitHandle=(e)=>{
let newlist =this.state.list;
let value = this.state.value;
//旧方法 数组添加
//newlist.concat().push(this.state.value);
this.setState({
list:[value,...newlist] //es6 数据合并
})
this.state.value='';
}
deleteOne=(key)=>{
//官方所 state不要直接修改 不允许我们直接改变 性能不好
//注意这里一定要复制一份再操作
var list =[...this.state.list];
//操作复制的这一份 坑
list.splice(key,1);
//重新设置
this.setState({
list
})
}
}
export default TodoList;
注意这里我们单独把列表抽离为一个子组件
TodoItem .js
import React,{Component} from 'react';
class TodoItem extends Component{
constructor(props) {
super(props);
}
render(){
return(
<li onClick={this.remove}>
{this.props.content}
</li>
)
}
//注意this的指向
remove=()=>{
//es6 数据结构 ,获取父组件的方法
const {deleteOne,keys}=this.props;
//执行父组件的deleteOne方法,并且把索引传递回去
deleteOne(keys)
}
}
export default TodoItem;
ps:抽离后一定要注意this的指向。。。。
大功告成,如果想更加完美,就优化代码,更加符合react规范 。。。
import React,{Component,Fragment} from 'react';
import './App.css';
import TodoItem from './TodoItem'
class TodoList extends Component{
constructor(props) {
super(props);
this.state={
value:'',
list:[]
}
}
render(){
return(
<Fragment>
<label htmlFor="username">用户名:</label>
<input type='text' id="username" className='input' value={this.state.value}
onChange={this.changeValue}
/><button onClick={this.submitHandle}>提交</button>
<ul>
{
this.getTodo()
}
</ul>
</Fragment>
)
}
getTodo(){
return this.state.list.map((item,index)=>{
return (
<div key={index}>
<TodoItem content={item} index={index}
deleteOne={this.deleteOne}
/>
{/* 注意这里有个坑,子组件TodoItem明明加了key一直报错,是因为要加到父级div上面才可以
<li onClick={this.remove}
>
{this.props.content}
</li>
*/}
</div>
)
})
}
//input 改变
changeValue=(e)=>{
let v =e.target.value;
// this.setState({
// value::v
// })
//使用最新版的setState 注意返回的是() 坑哦
//异步哦 v的值要提前存储起来使用哦
this.setState(()=>({
value:v
}))
}
//新增
submitHandle=(e)=>{
let newlist =this.state.list;
let value = this.state.value;
//newlist.push(this.state.value);
// this.setState({
// list:[value,...newlist] //es6 数据合并
// })
//this.state.value='';
//es6 返回的新函数 对象 注意prevState 保存的是之前的state
//prevState == this.state
this.setState((prevState)=>({
list:[prevState.value,...prevState.list],
value:''
}))
}
deleteOne=(key)=>{
/*
//官方所 state不要直接修改 不允许我们直接改变 性能不好
//注意这里一定要复制一份再操作
//重新设置
this.setState({
list
})
*/
//es6 最新写法
this.setState((prevState)=>{
var list =[...prevState.list];
//操作复制的这一份 坑
list.splice(key,1);
return {
list
}
}
)
}
}
export default TodoList;
优化方案如下:
1:使用了箭头函数改变this指向,当然也可以再constructor里面bind(this)
2:使用了抽离函数ui,在ui中把渲染抽离getTodo方法,方便维护
3:使用了最新的setState,可以返回一个对象函数,注意返回对象一定要加(),否则报错哦
4:使用了ES6的props结构,简化代码
5:使用了最新setState中的prevState,可以直接获取state状态啦,注意看代码写法
@最后再说一句,父组件可以给子组件传递值,但是子组件千万不能修改这个传递的值,这个值是只读属性,修改会报错,就比如这里的list如果传递过来,千万不能修改,修改报错!!
OK,大功告成,每天学习一点点,加油~~~~~~~