跟著網(wǎng)上各種教程入門react,決定做一個todolist來加深對react的理解
因為之前學(xué)過一陣子vue,用vue做的todolist直接把最終的效果圖拿來重新用react做
上圖就是用vue做的
說一下這個todo具備的功能:
1.輸入框輸入后直接按回車或者點擊新增按鈕時,將文本添加到下面展示列表部分。
2.每項前的checkbox勾選后文本部分標(biāo)記已完成并且不能編輯
3.每項鼠標(biāo)劃過在最右端出現(xiàn)刪除的'x'點擊可以刪除該項
4.文本部分用的input[type='text'],點擊文本可以修改文本。當(dāng)發(fā)生失焦事件或者回車按下事件時,判斷與之前的文本是否一致,不一致彈出確認(rèn)框,確認(rèn)框點擊確認(rèn)進行修改,點擊取消還原成之前的文本內(nèi)容。
問題出現(xiàn)在,用react做的時候,input[type='text']的屬性用value必須得配合onChange,但是這一塊我不會做,
如果用defaultValue出現(xiàn)一個情況就是,不點擊刪除確認(rèn)的話,顯示沒問題,但是點擊刪除一項時,defaultValue不會再次渲染,所以刪除后的列表顯示的文本內(nèi)容還是刪除之前的內(nèi)容。
希望哪位大神耐心看一下我的代碼,幫我一下~
我也希望有對我代碼優(yōu)化改進之類的建議
貼一下改動后的代碼:
import React, { Component } from 'react';
import './App.less';
//去除兩邊空格
function trim(str){
return str.replace(/(^\s*)|(\s*$)/g, "");
}
//新增事項組件
class AddPanel extends Component {
constructor(props){
super(props);
this.addhandler = this.addhandler.bind(this);
/*this.ButtonAddHandler = this.ButtonAddHandler.bind(this);*/
}
addhandler(e){
var ListDataArr = this.props.ListDataArr;
var inputStr = this.input.value;
var trimStr = trim(inputStr);
if(( e.target.type === 'text' && e.keyCode === 13 ) || e.target.type === 'button'){
if(trimStr){
ListDataArr.push({
text:trimStr,
ischecked: false
});
this.props.SetInputToListData(ListDataArr);
}
this.input.value = '';
}
}
render(){
return (
<div className="addpanel clearfix">
<button type="button" onClick={this.addhandler}>新增</button>
<div className="addinput">
<input type="text" placeholder="請輸入添加事項" onKeyDown={this.addhandler} ref={input => this.input=input} />
</div>
</div>
)
}
}
//顯示代辦事項組件
class ListPanel extends Component {
constructor(props){
super(props);
this.state = {
inputText: ''
};
this.changeChecked = this.changeChecked.bind(this);
this.modification = this.modification.bind(this);
this.keydownModification = this.keydownModification.bind(this);
this.deletehandler = this.deletehandler.bind(this);
this.textrecord = this.textrecord.bind(this);
this.bindinputvalue = this.bindinputvalue.bind(this);
}
changeChecked(index){
var ListDataArr = this.props.ListDataArr;
ListDataArr[index].ischecked = !ListDataArr[index].ischecked;
this.props.checkhandler(ListDataArr);
}
modification(index,e){
var ListDataArr = this.props.ListDataArr;
var afterStr = trim(e.target.value);
if(afterStr === this.state.inputText){
ListDataArr[index].text = afterStr;
this.props.checkhandler(ListDataArr);
}else{
var conf = window.confirm('確定修改么?');
if(conf){
ListDataArr[index].text = afterStr;
this.props.checkhandler(ListDataArr);
}else{
ListDataArr[index].text = this.state.inputText;
this.props.checkhandler(ListDataArr);
}
}
}
keydownModification(index,e){
if(e.keyCode === 13){
this.modification(index,e);
}
}
deletehandler(index,e){
var ListDataArr = this.props.ListDataArr;
var conf = window.confirm('確定刪除么?');
if(conf){
ListDataArr.splice(index,1);
this.props.checkhandler(ListDataArr);
}
}
textrecord(index,e){
this.setState({
inputText: e.target.value
})
console.log(e.target.value);
}
bindinputvalue(index,e){
var ListDataArr = this.props.ListDataArr;
ListDataArr[index].text = e.target.value;
this.props.checkhandler(ListDataArr);
}
render(){
var ListDataArr = this.props.ListDataArr;
return (
<div className="listpanel">
<h3>您的待辦事項</h3>
<ul>
{
ListDataArr.map((item,index) => {
return (
<li key={index+1}>
<span>
<input type="checkbox" onChange={this.changeChecked.bind(null,index)} checked={item.ischecked?true:false}/>
{index+1+": "}
</span>
<div>
<input type="text" value={item.text} onChange={this.bindinputvalue.bind(null,index)} onFocus={this.textrecord.bind(null,index)} onBlur={this.modification.bind(this,index)} onKeyDown={this.keydownModification.bind(null,index)} disabled={item.ischecked?true:false} className={item.ischecked?'done':''}/>
</div>
<i onClick={this.deletehandler.bind(null,index)}></i>
</li>
)
})
}
</ul>
</div>
);
}
}
class Statistics extends Component {
render(){
var ListDataArr = this.props.ListDataArr,
total = ListDataArr.length,
finished = 0,
nofinished = 0;
ListDataArr.forEach(function(item,index){
if(item.ischecked){
finished++;
}else{
nofinished++;
}
})
return (
<div className="statisticsPanel">
共: <span className="color01">{total}</span> 個事項, 其中 完成事項: <span className="color02">{finished}</span> 個, 代辦事項: <span className="color03">{nofinished}</span> 個.
</div>
);
}
}
class App extends Component {
constructor(props){
super(props);
this.state = {
ListDataArr: storage.fetch(),
}
this.SetInputToListData = this.SetInputToListData.bind(this);
}
SetInputToListData(arr){
arr.map((item,index) =>{
return (item.id = index);
});
this.setState({
ListDataArr: arr
});
storage.save(arr);
}
render() {
console.log(JSON.stringify(this.state.ListDataArr));
return (
<div id="app">
<AddPanel ListDataArr={this.state.ListDataArr} SetInputToListData={this.SetInputToListData}></AddPanel>
<ListPanel ListDataArr={this.state.ListDataArr} checkhandler={this.SetInputToListData}></ListPanel>
<Statistics ListDataArr={this.state.ListDataArr}></Statistics>
</div>
);
}
}
//創(chuàng)建localstorage
var storageName = 'todolist-react';
const storage = {
fetch(){
return JSON.parse(localStorage.getItem(storageName) || '[]');
},
save(jsondata){
localStorage.setItem(storageName,JSON.stringify(jsondata));
}
}
export default App;
按照一樓給的解決思路,把defaultValue換成了value 并添加onChange事件
現(xiàn)在可以達(dá)到我想要的功能效果了
雖然功能實現(xiàn)了,但是我覺得我的代碼看著很混亂,有些代碼感覺很冗余但是又不知道該如何優(yōu)化提煉,比如ListPanel組件里的
<input type="text" value={item.text} onChange={this.bindinputvalue.bind(null,index)} onFocus={this.textrecord.bind(null,index)} onBlur={this.modification.bind(this,index)} onKeyDown={this.keydownModification.bind(null,index)} disabled={item.ischecked?true:false} className={item.ischecked?'done':''}/>
這部分,我添加了好多事件,這一塊是否可以去掉不必要的代碼,或者這些事件所調(diào)用的方法是否可以整合去寫,再有 每個事件我想傳遞當(dāng)前對象作為參數(shù),而我寫的是.bind(null,index)傳遞的是該對象在數(shù)組的索引值
北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
北大青鳥中博軟件學(xué)院創(chuàng)立于2003年,作為華東區(qū)著名互聯(lián)網(wǎng)學(xué)院和江蘇省首批服務(wù)外包人才培訓(xùn)基地,中博成功培育了近30000名軟件工程師走向高薪崗位,合作企業(yè)超4
中公教育集團創(chuàng)建于1999年,經(jīng)過二十年潛心發(fā)展,已由一家北大畢業(yè)生自主創(chuàng)業(yè)的信息技術(shù)與教育服務(wù)機構(gòu),發(fā)展為教育服務(wù)業(yè)的綜合性企業(yè)集團,成為集合面授教學(xué)培訓(xùn)、網(wǎng)
達(dá)內(nèi)教育集團成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團項目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗,技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。