上次寫了一個React生命周期詳解就缆,給新手看還是不是特別容易理解(其實我也是新手)宪萄,這邊再做一個React的todolist的dome做一個示例州叠。我也是剛接觸沒多久React 希望大家共同進步后众!
下邊直接上示例代碼:
項目結(jié)構
我這里是用的webpack做的打包,每個人的習慣不一樣印屁,所以目錄結(jié)構不必強求一樣循捺,只要自己理解就好。
app--|
|--components
| |-- Input
| | |--index.jsx
| | |--index.less
| |--List
| |--index.jsx
| |--index.less
|--containers
| |--TodoList
| |--index.jsx
|--index.jsx
|--index.html
示例代碼
展示組件
Input子組件
// ../../components/Input/index
import React from 'react'
// 組件的樣式文件
import './index.less'
class Input extends React.Component {
constructor(props, context) {
super(props, context)
this.state = {
// 初始化state
value: ''
}
}
handleChange(e) {
this.setState({
value: e.target.value
})
}
handleSubmit(e) {
let text = this.state.value;
// 判斷是否是回車鍵 并且text不為空才提交text
if (e.keyCode == 13 && text.trim()) {
this.props.addTodoList (text);
// 提交后清空輸入框value值
this.setSate({
value: ''
})
}
}
render() {
return(
<div className="header">
<input type="text" onKeyUp={this.handleSubmit.bind(this)} onChange={this.handleChange.bind(this)} value={this.state.value}/>
</div>
)
}
}
export default Input;
樣式文件在此就不展示出來了雄人。
這里需要說明一下我在學習時學到的幾個知識點:
-
class類名
因為是class
在ES6中是定義類从橘,所以在DOM中class
要寫成className
- 給某個元素增加事件時最好是都帶上
bind(this)
,例如:onChange={this.handleChange.bind(this)}
础钠,因為在事件函數(shù)中一般都會使用到state
或者props
中的屬性或者方法恰力,雖然有的時候也許用不到,不過還是養(yǎng)成一個寫上的習慣旗吁。 - 輸入框的
value
值踩萎,一般如果你是默認攜帶的有值,不可以直接寫value="xxx"
react會有這個值可能需要改變很钓,這種寫法在change中無法改變之類的警告香府, 如果真的需要有默認值可以寫成defaultValue="xxxx"
董栽。我這里是將state
中的value
賦值在input的屬性里,然后通過input的onChange
來設置state
做到改變value值企孩。這也是我在學習過程中在一個視頻教程上講到的約束性寫法锭碳。
List子組件
// ../../components/List/index
import React from 'react'
import './index.less';
class List extends React.Component {
constructor(props, context) {
super(props, context)
}
handleClick(id){
this.props.deleteItem(id)
}
render() {
let todos = this.props.todos ? this.props.todos : [];
return (
<div className="list-content">
<ul className="list">
{
todos.map((item, index) => {
return (
<li key={index} className="item">
{item.text}
<span className="delete-btn" onClick={this.handleClick.bind(this, item.id)}>X</span>
</li>
)
})
}
</ul>
</div>
)
}
}
export default List;
業(yè)務組件
TodoLIst組件
// ./containers/TodoList/index
import React from 'react'
import Input from '../../components/Input/index';
import List from '../../components/List/index';
class TodoList extends React.Component {
constructor(props, context) {
super(props, context)
this.state = {
todos: []
}
}
// 刪除單挑數(shù)據(jù)
deleteItem(id) {
let data = this.state.todos;
this.setState({
todos: data.filter((item, index) => {
if (item.id !== id) {
return item;
}
})
})
}
// 添加單條數(shù)據(jù)
addTodoList(value) {
const id = Date.now();
this.setState({
todos: this.state.todos.concat({
id: id,
text: value
})
})
}
render() {
return (
<div>
<Input addTodoList={this.addTodoList.bind(this)} />
<List todos={this.state.todos} deleteItem={this.deleteItem.bind(this)} />
</div>
)
}
};
export default TodoList;
這里的展示組件,業(yè)務組件我說一下我的理解:
- 展示組件:負責頁面的渲染勿璃,效果展示擒抛。其數(shù)據(jù)來源是業(yè)務組件傳遞過來的
props
,或者自身的state
补疑,其處理函數(shù)都由業(yè)務組件定義的函數(shù)通過props
傳遞過來歧沪,在自身函數(shù)中與業(yè)務組件做數(shù)據(jù)交互。 - 業(yè)務組件: 負責與服務器做ajax請求莲组、數(shù)據(jù)的獲取诊胞、業(yè)務邏輯的定義等業(yè)務交互。例如本案例的添加數(shù)據(jù)的函數(shù)锹杈,刪除數(shù)據(jù)的函數(shù)都是在TodoList組件定義好 厢钧,傳遞給對應的子組件。而List列表的數(shù)據(jù)也是由這個組件傳遞過去的嬉橙。
入口文件
// index.jsx
import { render } from 'react-dom';
// 公共樣式
import './static/css/common.less'
import TodoList from './containers/TodoList/index'
render(
<TodoList />,
document.getElementById('root')
)
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>react todo list</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
展示效果
1516766313669.jpg