效果如下:

image.png
分析组件:
1.头部:标题
2.内容:列表项+删除
3.尾部:添加列表项
4.包裹所有组件的App.js,在这个大的组件包含所有的属性及操作

image.png
标题
//header.js
import React,{Component } from 'react';
import "./header.css"
class Header extends Component{
render(){
return (
<div className="header">
任务便签
</div>
)
}
}
export default Header
在App.js引出:
<Header />
尾部添加
分析:
1.因为所有的操作都会在App.js里面去操作,所以子组件的所以初始化的属性都需要通过父组件传值给子组件;比如输入框的value属性值
2.通过onChange事件获取用户输入的值,试想:怎么让用户输入的值显示在输入框里面呢:也就是说我怎么把输入的值赋值给父组件的value,这就需要使用子组件触发父组件的函数,并传值给父组件:this.props.这个方法(传的值)
3.当点击添加按钮的时候,我需要将输入的值追加到定义的List,同样在子组件点击按钮,触发父组件的方法
footer.js
class Header extends Component{
handleInput(e){
this.props.handleInput(e.target.value)
}
handleAdd(){
this.props.handleAdd()
}
render(){
return (
<div className="footer">
<input type="text" value={this.props.value} onChange={this.handleInput.bind(this)}>
<button onChlick={this.handleAdd.bind(this)}>添加</button>
</div>
)
}
}
//父组件
constructor(props) {
super(props)
this.state = {
list: [{
name: 'learn english',
status: 0
}, {
name: 'Learn guitar',
status: 0
}, {
name: 'weight less than 100',
status: 0
}, {
name: 'have 100,000 deposit',
status: 0
}],
value:"",
}
}
//父组件接受子组件传的值
handleInput(val){
this.setData({
value:val
})
}
handleAdd(){
if(!this.state.value){
return false
}
this.setState({
list:[...this.state.list,{
name:this.state.value,
status:0,
}],
value:""
})
}
render{
return (
<Footer value={this.state.list} handleInput={this.handleInput.bind(this)} handleAdd={this.handleAdd.bind(this)} />
)
}
中间列表项
分析:
1.列表项是由一个单选框,名字,删除按钮
2.因为列表项可能会有很多,则使用map方法
3.单选框的选中状态是由List的status为1才表示已选中,当选中状态发生改变时,怎么让list的status实时去改变呢,所以需要出发父组件的方法,
4.当该列表项为选中时,则该文字会加上删除线:利用text-decoration-line:值为"line-through"时表示文字中间部分画线
5.点击删除按钮是需要删除当前用户点击的那一行,所以怎么判断用户是当前那一行是一个问题:
6.已完成的数量是表示status为1的个数
// this.handleclick.bind(this,要传的参数) handleclick(传过来的参数,event)
class ListItem extends Component{
handleFished(name){
// 子组件向父组件传值
// 在子组件点击的li得到的值,交给父组件去做交互
this.props.handleFished(name);
}
handleDelete(name){
this.props.handleDelete(name)
}
render(){
return (
<ul>
{this.props.data.map((item,index)=>{
return (
<li key={index} className="listItem">
<input type="checkbox" checked={item.status===1} onChange={this.handleFished.bind(this,item.name)} />
<span style={{textDecorationLine:item.status===0?'none':'line-through'}}>{item.name}</span>
<button className="delete" onClick={this.handleDelete.bind(this,item.name)}>删除</button>
</li>
)
})}
<li>已完成:{this.props.finished}/总数:{this.props.data.length}</li>
</ul>
)
}
}
export default ListItem
父组件:
constructor(props) {
super(props)
this.state = {
list: [{
name: 'learn english',
status: 0
}, {
name: 'Learn guitar',
status: 0
}, {
name: 'weight less than 100',
status: 0
}, {
name: 'have 100,000 deposit',
status: 0
}],
finished:0,//已完成的个数
}
}
handleFished(name){
const list=[];
let sum=0;
this.state.list.forEach((item,index){
//判断用户点击的是当前所点击的那一行
if(item.name=name){
let val=this.state.list[index]
let obj={
name:val.name,
status:val.status===0?1:0
}
list.push(Object.assign({},obj))
this.setState({
list:list
},()=>{
this.state.list.forEach(item=>{
if(item.status===1){
sum++;
}
this.setState({
finished:sum
})
})
})
} else{
list.push(item)
}
})
}
handleDelete(name){
let arr=this.state.list.filter((item)=>{
return item.name!==name
})
this.setState({
list:arr
})
}
render(){
return(
<ListItem data={this.state.list} finished={this.state.finished} handleFished={this.handleFished.bind(this)} handleDelete={this.handleDelete.bind(this)} />
)
}