一、写作缘由
最近学习了React基础,想找个小项目复习巩固一下,就写了一个简单的日程表组件。虽然只是一个小项目,但是开发中间出现了很多次错误,简单记录一下。
二、组件展示
三、功能描述
- 右上角可以添加新日程,放在正在执行类别中
- 日程表下有三种类型的日程:正在执行、已完成、已删除
- 点击状态切换:正在执行-->已完成-->已删除
四、组件组合
在React中几乎不使用继承,而是使用组合。在本例中,正在执行、已完成、已删除三个类别的日程只是标题和前面的图标不一样,其他基本一样。在面向对象设计方法中,这简直是一个完美的继承模型,但是在React中却是使用组合实现的。在Schedule组件中将具有特殊性的东西提取出来,让ExecutingSchedule、FinishedSchedule和DeletedSchedule来提供,从而通过组合实现了继承的效果。
五、组件源码
ScheduleList.js
import React, { Component } from 'react'
import './Schedule.css'
function ScheduleSample(props){
let schedules = props.schedules;
return (
<div>
<h3>{props.title}</h3>
<ul className={props.icon}>
{
schedules.map((schedule)=>{
return <li key={schedule.id} onClick={(e)=>{props.handleClick(schedule)}} status={schedule.status}><i></i>{schedule.content}</li>
})
}
</ul>
</div>
)
}
const Schedule = React.memo(ScheduleSample);
function FinishedSchedule(props){
return (
<Schedule title="已完成的日程" {...props} icon='finished'></Schedule>
)
}
function DeletedSchedule(props){
return (
<Schedule title="已删除的日程" {...props} icon='deleted'></Schedule>
)
}
function ExecutingSchedule(props){
return (
<Schedule title="正在执行的日程" {...props} icon='executing'></Schedule>
)
}
export default class ScheduleList extends Component {
constructor(props){
super(props);
this.state = {
scheduleText: "",
scheduleCount: 9,
scheduleList: [
{id: 1, content: "看电视", status: "executing"},
{id:2, content: "做作业", status: "executing"},
{id:3, content: "打篮球", status: "executing"},
{id: 4, content: "看电视", status: "deleted"},
{id:5, content: "做作业", status: "deleted"},
{id:6, content: "打篮球", status: "deleted"},
{id: 7, content: "看电视", status: "finished"},
{id:8, content: "做作业", status: "finished"},
{id:9, content: "打篮球", status: "finished"}
]
};
}
handleInputChange = (e)=>{
let val = e.target.value;
this.setState({scheduleText: val});
}
addSchedule = ()=>{
if(this.state.scheduleText){
this.setState((prevState)=>({
scheduleCount: (prevState.scheduleCount + 1),
scheduleList: prevState.scheduleList.concat({id: (prevState.scheduleCount+1), content: prevState.scheduleText, status: "executing"}),
scheduleText: "",
}));
}
}
statusChange = (s)=>{
const key = s.id;
const status = s.status;
this.setState((prevState)=>{
let scheduleList = prevState.scheduleList;
let scheduleObj = scheduleList.find(((schedule)=>schedule.id === key));
if(status === 'executing'){
scheduleObj.status = 'finished';
}else if(status === 'finished'){
scheduleObj.status = 'deleted';
}else{
}
return {scheduleList}
});
}
render() {
return (
<div className='schedule-list'>
<div className='schedule-list-header'>
<h2>日程列表</h2>
<div>
<input className='input-add' type='text' value={this.state.scheduleText} onChange={this.handleInputChange}/>
<button className='button-add' onClick={this.addSchedule}>添加日程</button>
</div>
</div>
<div className='schedule-list-content'>
<ExecutingSchedule schedules={this.state.scheduleList.filter((schedule)=>schedule.status === 'executing')} handleClick={this.statusChange}></ExecutingSchedule>
<FinishedSchedule schedules={this.state.scheduleList.filter((schedule)=>schedule.status === 'finished')} handleClick={this.statusChange}></FinishedSchedule>
<DeletedSchedule schedules={this.state.scheduleList.filter((schedule)=>schedule.status === 'deleted')} handleClick={this.statusChange}></DeletedSchedule>
</div>
</div>
);
}
}
ScheduleList.css
ul{
list-style-type: none;
}
.deleted{
list-style-image: url('deleted.png');
}
.finished{
list-style-image: url('finished.png');
}
.executing{
list-style-image: url('executing.png');
}
li:hover{
background-color: aliceblue;
}
.schedule-list{
box-sizing: border-box;
width: 40%;
background-color: antiquewhite;
}
.schedule-list-header{
display: flex;
justify-content: space-between;
align-items: center;
margin-left: 20px;
margin-right: 20px;
}
.schedule-list-header>h2{
order: 1
}
.schedule-list-header>div{
order: 2
}
.button-add{
margin-left: 1px;
}
六、重要知识点记录
- 列表数据渲染使用map
(
<div>
<h3>{props.title}</h3>
<ul className={props.icon}>
{
schedules.map((schedule)=>{
return <li key={schedule.id} onClick={(e)=>{props.handleClick(schedule)}} status={schedule.status}><i></i>{schedule.content}</li>
})
}
</ul>
</div>
)
2.对象列表中给定条件的对象的查找
this.state = {
scheduleText: "",
scheduleCount: 9,
scheduleList: [
{id: 1, content: "看电视", status: "executing"},
{id:2, content: "做作业", status: "executing"},
{id:3, content: "打篮球", status: "executing"},
{id: 4, content: "看电视", status: "deleted"},
{id:5, content: "做作业", status: "deleted"},
{id:6, content: "打篮球", status: "deleted"},
{id: 7, content: "看电视", status: "finished"},
{id:8, content: "做作业", status: "finished"},
{id:9, content: "打篮球", status: "finished"}
]
};
let scheduleObj = this.state.scheduleList.find(((schedule)=>schedule.id === key));
let schedules = this.state.scheduleList.filter((schedule)=>schedule.status === 'deleted'));
七、问题记录
- 事件处理函数中的this指向问题
- 数据传递过程中的undefined问题