todolist-react版(9.20-9.21)

# 设计效果

 

一. 框架
设计一个todolist,可以添加并记录今天做的事情,分为未完成和已完成,并且每个记录可以删除,并且统计记录总数和完成的数量
# 数据结构
父组件todoList包括输入框添加组件和列表数据组件
# 组件划分
todoList组件/输入框添加组件/列表数据组件
# 具体实现
父组件list
  把添加任务部分和列表部分记录数据集合起来,用来实现添加任务,更新任务总数,完成任务总数
  1. 父组件标题是ToDoList, h1, 未完成的样式,背景颜色#DFFCB5,color 颜色 #2EB872,完成样式,背景颜色#FFFA9D,颜色#FF9A3C,删除线 textDecoration: 'line-through'
  2. 初始化时设置列表list的默认数据及初始化完成数量参数
  3. 父组件添加任务方法更新任务列表list;完成任务状态改变时更新完成数量并更新;更新总数方法当删除时更新总数及对象传出去.
  4. render(){return ()},dom包括标题/列表数据需要通过map来遍历/完成数和总数
列表item组件
  勾选完成和删除数据,显示列表数据
 1. 处理完成的任务,完成时需要切换状态,并把id,名称,状态等数据通过props传出去
 2. 删除把props接收到的item传出去,组件那里需要通过item={item}来接收
 3. render(){return ()},dom来处理完成和未完成样式及勾选框/名称/删除按钮
 4. 初始化时绑定事件,如this.handleFinished = this.handleFinished.bind(this)
输入任务,添加任务组件
  给input输入框绑定ref事件,添加任务判断任务列表个数来设置id,添加任务并清空输入框
 1. 添加任务,通过绑定ref来获取到输入框的值并判断值是否为空,如为空提示信息并返回,否则添加任务,添加任务时通过props获取到列表总数来设置id,如果列表总数大于0,id取列表总数值否则为0,如果输入框存在且值不为空时,设置对象id/name(输入框的值)/状态,清空输入框的值,通过props添加任务
 2. render(){return ()},dom Task子标题,输入框绑定ref,按钮处理添加任务
 # 样式分析
 父组件 container 

 # 复盘应用到的知识
 1. react 实现构造方法constructor,必须实现super();
 2. react 绑定ref 需要建立ref,例子 this.myText = React.createRef(),dom ref={this.myText}.
 3. react的事件需要绑定的,例子 处理单击事件this.handleClick = this.handleClick.bind(this).
 4. 获取input的值,需要获取到current对象中的value.
 5. 调用父组件方法,例子this.props.addNewTask(obj),调用父组件的值 this.props.item.status.
 6. 调用state中的值,this.state, 更新state,this.setState({name: 'sdf'}).
 7. react render (){} 函数中可以添加变量以方便在return()中使用
 8. react 设置样式有两种,一是通过className="name",另一个种是style={style},style是一个对象,每个样式结束用逗号隔开.
 9. 在react 中遍历数组时用map,且组件也就是=>后面的组件不需要用{}来包裹
 10. 媒体尺寸适配, 
 @media screen and (max-width: 767px) {
   .container {
     ...
   }
   h3 {
     ....
   }
 }

 上代码如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>ToDoList</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="./main.css">
    <script src="../Build/react.development.js"></script>
    <script src="../Build/react-dom.development.js"></script>
    <script src="../Build/babel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/babel">
      // todolist 输入框
      class Dialog extends React.Component {
        constructor (props) {
          super(props)
          this.myText = React.createRef();
          this.handleClick = this.handleClick.bind(this);
        }
        handleClick () {
          if (!this.myText.current.value) {
            alert('请添加你的任务')
            return 
          }
          const len = this.props.nums;
          const newId = len > 0 ? len : 0;
          const value = this.myText.current.value;
          if (!value !== '') {
            const obj = {
              id: newId,
              name: value,
              status: 0
            };
            this.myText.current.value = '';
            this.props.addNewTask(obj);
          }
        }
        render () {
          return (
            <div className="dialog">
              <div>
                <h3>Task</h3>
                <input type="text" placeholder="今天做什么" ref={this.myText}/>
                <input type="button" value="添加" onClick={this.handleClick}/>
              </div>
            </div>
          )
        }
      }
      // listItem
      class ListItem extends React.Component {
        constructor(props) {
          super(props)
          this.handleFinished = this.handleFinished.bind(this)
          this.handleDelete = this.handleDelete.bind(this)
        }
        // 处理todolist完成
        handleFinished () {
          let status = this.props.item.status
          status = (status === 0 ? 1 : 0)
          let obj = {
            id: this.props.item.id,
            name: this.props.item.name,
            status: status
          }
          this.props.finishChange(obj)
        }
        // 删除todolist一项
        handleDelete () {
          this.props.totalChange(this.props.item)
        }
        render () {
          const item = this.props.item
          const unfinish = {
            backgroundColor: '#DFFCB5',
            color: '#2EB872'
          }
          const finish = {
            backgroundColor: '#FFFA9D',
            color: '#FF9A3C',
            textDecoration: 'line-through'
          }
          var itemStyle = item.status === 0 ? unfinish : finish;
          return (
            <li key={item.id} style={itemStyle}>
              <span onClick={this.handleFinished}
              id={item.id}
              className="check-btn"
              style={{backgroundColor: item.status === 0 ? '#fff': '#A1EAFB'}}>
              </span>
              <span>{item.name}</span>
              <span onClick={this.handleDelete} className="delete-btn">删除</span>
            </li>
          )
        }
      }
      // 数组
      class ToDoList extends React.Component {
        constructor(props) {
          super(props)
          this.state = {
            list: [{
              id: 0,
              name: 'react学习',
              status: 0
            }, {
              id: 1,
              name: 'vue学习',
              status: 0
            }],
            finished: 0
          }
        }
        addTask (newItem) {
          var allTask = this.state.list;
          allTask.push(newItem)
          this.setState({
            list: allTask
          });
        }
        updateFinished (todoItem) {
          console.log('------------updateFinished', todoItem);
          var sum = 0;
          this.state.list.forEach((item) => {
            if (item.id === todoItem.id) {
              item.status = todoItem.status;
            }
            if (item.status === 1) {
              sum++;
            }
          });
          this.setState({
            finished: sum
          })
        }
        updateTotal (todoItem) {
          var obj = []
          var sum = 0
          this.state.list.forEach((item) => {
            if (item.id !== todoItem.id) {
              obj.push(item)
              if (item.status === 1) {
                sum++
              }
            }
          })
          this.setState({
            list: obj,
            finished: sum
          })
        }
        render () {
          return (
            <div className="container">
              <h1>toDoList</h1>
              <Dialog addNewTask={this.addTask.bind(this)} nums={this.state.list.length}/>
              <ul>
                {
                  this.state.list.map((item, index) => 
                    <ListItem
                      item={item}
                      finishChange={this.updateFinished.bind(this)}
                      totalChange={this.updateTotal.bind(this)}
                      key={index}>
                    </ListItem>
                  )
                }
                <li>{this.state.finished}已完成 / {this.state.list.length}总数</li>
              </ul>
            </div>
          )
        }
      }
      ReactDOM.render(
        <ToDoList/>,
        document.getElementById('app')
      )
    </script>
  </body>
</html>

// main.css
.container {
	text-align: center;
	background-color: #f7f7f7;
	margin: 50px 20%;
	padding: 20px 0;
	height: 100%;
	border-radius: 5px;
}

.dialog {
	text-align: left;
	margin: 0 5%;
	padding: 30px 0;
}

.dialog div {
	/* overflow: hidden; */
	display: flex;
	justify-content: center;
	align-items: center;
}

h3 {
	display: inline-block;
	margin-left: 50px;
	margin-right: 20px;
	/* position: relative;
	top: 50%;
	transform: translateY(-50%); */
}

input[type="text"] {
	line-height: 40px;
	/* float: right; */
	width: 80%;
	border-radius: 5px;
	border: none;
	font-size: 16px;
	box-sizing: border-box;
	padding: 0 5px;
	border: 1px #ccc solid;
	outline: none;
	box-shadow: 0 0 10px #ccc;
}

input[type="button"] {
	margin-left: 20px;
	border: none;
	background-color: #A1EAFB;
	height: 40px;
	width: 110px;
	font-size: 18px;
	color: #fff;
	border-radius: 5px;
	/* float: right; */
}

ul {
	text-align: left;
	margin: 20px 5%;
	border-radius: 5px;
	border: 1px #bbb solid;
}

ul li {
	list-style: none;
	line-height: 50px;
	border-bottom: 1px #bbb solid;
	padding: 0 20px;
}

ul li:first-child {
	/* border-top-left-radius: 5px;
	border-top-right-radius: 5px; */
}

ul li:last-child {
	/* border-bottom-left-radius: 5px;
	border-bottom-right-radius: 5px; */
}

ul li:hover > .delete-btn {
	display: block;
}

.delete-btn {
	color: #ccc;
	float: right;
	cursor: pointer;
	display: none;
}

.check-btn {
	width: 13px;
	height: 13px;
	display: inline-block;
	border: 1px #ccc solid;
	border-style: outset;
	border-radius: 5px;
	margin-right: 20px; 
	cursor: pointer;
}
/* 
input[type="checkbox"] {
	border: 0;
	color: #fff;
	background-color: #A1EAFB;
} */

@media screen and (max-width: 767px) {
	.container {
		margin: 20px 5%;
	}

	h3 {
		margin-left: 0;
	}

  

 

posted @ 2021-09-21 21:00  TheYouth  阅读(74)  评论(0编辑  收藏  举报