實現需求:todolist實現增刪改查;javascript
實現思路:react組件劃分。由於用的是localstorage封裝了數據庫各個組件之間數據庫不能同步,因此設計組件的思路是在父組件裏進行增刪改查後的渲染操做(setstate),父組件app下有增刪改查操做,所以有四個子層級組件,考慮到剛開始作刪除功能的時候對li有操做,因此把對li的操做(刪除),ui樣式的變更和渲染統一放在了刪除todoitem組件裏,所以該組件的功能就是對li執行刪除操做,和一些事件處理,組件內容應該返回li和和刪除按鈕,可是li是一個數組,因此須要作一個循環去不停的渲染todoitem,因此設計一個父組件todomain,todomain的功能就是對數據執行map,map裏循環渲染todoitem組件,同事把數組傳給子組件todoitem,因此todomain應該是從app(app組件有增長組件傳遞的數據,並把該數組存到了數據庫(localDb),因此要獲取這個數組進行渲染)繼承數據,所以設計思路如圖:前端
app.js,首先看底部render的子組件:java
render(){
return (
<Card className="pannel">
<TodoHeader addTodo={this.addTodo.bind(this)} todos={this.state.todos} showAll={this.showAll.bind(this)} />
<TodoQuery ref="query" todos={this.state.todos} queryList={this.queryList.bind(this)} />
<TodoMain todos={this.state.todos} changeTodoState={this.changeTodoState.bind(this)} deleteTodo={this.deleteTodo.bind(this)} reviseTodo={this.reviseTodo.bind(this)}/>
<TodoRevise ref="modal" todos={this.state.todos} closeDialog={this.closeDialog.bind(this)} reviseContent={this.reviseContent.bind(this)}/>
</Card>
)
}
複製代碼
接下來看增長的渲染操做addTodo方法node
addTodo(todoItem){
if(!this.db.get('todos')){
this.db.set('todos',[]);
}
this.state.todos.unshift(todoItem);
if(this.state.todos.length != this.db.get('todos').length){
this.db.get('todos').unshift(todoItem);
}
this.db.set('todos',this.db.get('todos'));
this.setState({
todos:this.db.get('todos')
});
message.config({
top:48,
duration:1
});
message.success('增長成功!');
}
複製代碼
刪除操做deleteTodoreact
deleteTodo(timeId){
let i =0;
for(i=0;i<this.db.get('todos').length;i++){
if(this.db.get('todos')[i].timeId == timeId){
this.db.get('todos').splice(i,1);
}
}
this.state.todos.map((todo,index) => {
console.log(todo);
if(todo.timeId == timeId){
this.state.todos.splice(index,1);
}
});
this.setState({todos:this.state.todos});
this.db.set('todos',this.db.get('todos'));
message.config({
top:48,
duration:1
});
message.success('刪除成功!');
}
複製代碼
複製代碼
複製代碼
- queryList(queryArr){
message.config({
top:48,
duration:1
});
if(this.state.todos.length == this.db.get('todos').length && queryArr.length == 0){
message.warning('查詢內容不存在');
return;
}
if(queryArr.length == 0){
message.warning('當前list不存在查詢內容,已爲您轉到所有list');
this.setState({
todos:this.db.get('todos')
});
}else{
this.setState({
todos:queryArr
});
}
}
複製代碼
###TodoMain組件:jquery
- return (
<ul className="todo-list">
{this.props.todos.map((todo, index) => {
//return <li style={listStyle}>{this.props.todos[index].text}</li>
return <TodoItem key={index} text={todo.text} isDone={todo.isDone} lastReviseTime={todo.lastReviseTime} timeId={todo.timeId} index={index} {...this.props} />
//return <TodoItem key={index} {...todo} index={index} {...this.props}/>
//map對數組進行了遍歷,todo表示每個數組元素text,index表明索引,因此讓todoitem渲染的過程是一個循環的渲染過程,每次渲染不同,是動態組件渲染
//做爲動態組件,須要一個key,每次渲染的時候key不一樣,纔會顯示不一樣的渲染,是一個表示的渲染
})}
</ul>
)
複製代碼
###TodoItem組件webpack
- export default class TodoItem extends React.Component{
constructor(){
super();
this.state = {
checkAll:false
}
}
// 鼠標移入
handlerMouseOver(){
ReactDom.findDOMNode(this.refs.deleteBtn).style.display = "inline";
ReactDom.findDOMNode(this.refs.changeBtn).style.display = "inline";
}
// 鼠標移出
handlerMouseOut(){
ReactDom.findDOMNode(this.refs.deleteBtn).style.display = "none";
ReactDom.findDOMNode(this.refs.changeBtn).style.display = "none";
}
// 刪除當前任務
handlerDelete(){
this.props.deleteTodo(this.props.timeId);
console.log(this.props.timeId);
}
reviseTodo(){
this.props.reviseTodo(this.props.text,this.props.index,this.props.timeId);
}
render(){
let doneStyle = this.props.isDone ? {color: 'red'} : {color: '#57c5f7'};
return (
<li onMouseOver={this.handlerMouseOver.bind(this)} onMouseOut={this.handlerMouseOut.bind(this)} ref='checkList' > <span style={doneStyle} className="listContent">{this.props.text}</span> <Button ref="deleteBtn" onClick={this.handlerDelete.bind(this)} style={{'display': 'none'}} className="fr libtn-height">刪除</Button> <Button ref="changeBtn" style={{'display': 'none'}} className="change libtn-height" onClick={this.reviseTodo.bind(this)}>修改</Button> <span className='product-time'>建立時間:{this.props.timeId}</span><span className='revise-time'>最後修改時間:{this.props.lastReviseTime}</span> </li>
)
}
}
複製代碼
###TodoRevise組件git
- class TodoRevise extends React.Component {
constructor(){
super();
this.state={
visible: false
};
}
// 綁定鍵盤迴車事件,添加新任務
showModal(todo,index,timeId) {
this.setState({
visible: true,
reviseList: todo,
reviseIndex:index*1+1,
reviseTimeId:timeId
});
}
handleOk() {
let newList = document.getElementById('reviseinput').value;
let lastReviseTime = new Date().getTime();
this.state.reviseList = newList;
this.props.reviseContent(this.state.reviseList,this.state.reviseIndex,this.state.reviseTimeId,lastReviseTime);
}
handleCancel() {
this.props.closeDialog();
}
copyList(){
document.getElementById('reviseinput').value = this.state.reviseList;
}
keyComplete(event){
let lastReviseTime = new Date().getTime();
if(event.keyCode == 13){
let newList = document.getElementById('reviseinput').value;
this.state.reviseList = newList;
this.props.reviseContent(this.state.reviseList,this.state.reviseIndex,this.state.reviseTimeId,lastReviseTime);
}
}
render() {
return (
<div> <Modal title="修改列表內容" visible={this.state.visible} onOk={this.handleOk.bind(this)} onCancel={this.handleCancel.bind(this)}> <div>您正在修改第{this.state.reviseIndex}條,修改內容爲<p className="revise_content" onClick={this.copyList.bind(this)}>{this.state.reviseList}</p></div> <p>在下面輸入框中對原內容進行修改(支持回車鍵保存)</p> <Input type="text" id="reviseinput" placeholder="點擊藍色字體將內容複製到輸入框" onKeyUp={this.keyComplete.bind(this)}></Input> </Modal> </div>
)
}
}
export default TodoRevise;
複製代碼
###總結與思考es6
####react渲染性能優勢:github
var ulRoot = ul.render()
document.body.appendChild(ulRoot)
也就是react中:
ReactDOM.render(<App/>,document.getElementById('ulRoot'));
複製代碼
來逐層計算子節點,而後把子節點拋到根節點(ulRoot)下。
####react使用