这次给大家带来的是用react实现todolist的详细步骤,这篇文章就给大家好好分析一下。
首先讲一下要实现的功能吧
(1)可以添加任务;
(2)已完成任务以及未完成任务的颜色区分开;
(3)进行添加任务,修改任务状态,以及删除任务时,下面的任务完成数目和任务总数要进行变化;
以上就是要实现的功能。
二. 接下来该如何设计呢?
(1)任务存储的数据结构:
list: [{
id: 0,
name: '吃饭',
status: 0
}, {
id: 1,
name: '睡觉',
status: 0
}, {
id: 2,
name: '打豆豆',
status : 0
}]
每个任务都有自己的id,任务名,以及任务的状态,任务的id除了标识任务的唯一性,还可以作为列表项的key值。我们都知道在react中使用列表,列表的每一项必须有个key值,这样会使得每个列表项可以快速定位,在执行diff算法时减少不必要的查询,从而对性能的提升有所帮助。
(2)组件的划分
todolist整体作为一个大组件;
列表中的每个列表项(listitem)作为一个组件;
任务的添加框(dialog)作为一组件。
三. 具体实现
以列表项listitem的实现为例:
将列表项单独划分为一个组件是必须的,这样使得每个单独的条目都是独立的,使得代码的逻辑更加简单,增强代码的复用性,维护也会变得更简单。
当然聪明的你肯定会想到一个问题:每一个task的状态改变或者task的添加删除,task的完成数目和总数目都是会改变的,可是每个listitem都是相互独立的,如何实现呢?这时就要用到父子组件之间的通信了。
如果你也是和我一样react的初学者,百度一下就会出现很多文章都会讲父子组件间如何通信,下面我简单说一下自己简单粗暴的理解:
在父子组件中定义改变state数据的方法,将方法以props的形式传递给子组件,在子组件中触发事件处理程序,然后满足某种条件的话就执行父组件传来的函数。
具体代码如下:
父组件中的代码:
import react, { component } from 'react';
import listitem from './listitem';
import dialog from './dialog';
import './main.css';
class todolist extends component {
constructor (props) {
super(props);
//初始任务列表
this.state = {
list: [{
id: 0,
name: '吃饭',
status: 0
}, {
id: 1,
name: '睡觉',
status: 0
}, {
id: 2,
name: '打豆豆',
status : 0
}],
finished: 0
};
}
//添加新任务,在组件中以props的形式传递给子组件
addtask (newitem) {
var alltask = this.state.list;
alltask.push(newitem);
this.setstate({
list: alltask
});
}
//更新完成的任务,在组件中以props的形式传递给子组件
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
});
}
//更新任务总数,在组件中以props的形式传递给子组件
updatetotal (todoitem) {
var obj = [], 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>
<ul>
{ this.state.list.map ((item, index) =>
<listitem
item={item}
finishedchange={this.updatefinished.bind(this)}
totalchange={this.updatetotal.bind(this)}
key={index}
/>
)}
<li>{this.state.finished}已完成 / {this.state.list.length}总数</li>
</ul>
<dialog addnewtask={this.addtask.bind(this)} nums={this.state.list.length}/>
</div>
);
}
}
export default todolist;
子组件中的代码:
import react, { component } from 'react';
class listitem extends component {
constructor (props) {
super(props);
this.handlefinished = this.handlefinished.bind(this);
this.handledelete = this.handledelete.bind(this);
}
handlefinished () {
var status = this.props.item.status;
status = (status === 0 ? 1 : 0);
var obj = {
id: this.props.item.id,
name: this.props.item.name,
status: status
}
this.props.finishedchange(obj); //执行父组件传来的方法
}
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>
);
}
}
export default listitem;
以上是对这个小练习的一个总结,如果你也和我一样是个react新手的话,写完这个相信你对react一定会有更近一步的理解
相信看了以上介绍你已经掌握了方法,更多精彩请关注其它相关文章!
相关阅读:
如何用vue实现登录验证
怎样使用vue的自定义指令完成一个下拉菜单
用jquery做出对数组去重及排序的操作
以上就是用react实现todolist的详细步骤的详细内容。
