上次寫了一個React生命周期詳解,給新手看還是不是特別容易理解(其實我也是新手),這邊再做一個React的todolist的dome做一個示例。我也是剛接觸沒多久React 希望大家共同進步!
下邊直接上示例代碼:
項目結構
我這里是用的webpack做的打包,每個人的習慣不一樣,所以目錄結構不必強求一樣,只要自己理解就好。
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)}
,因為在事件函數中一般都會使用到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: []
}
}
// 刪除單挑數據
deleteItem(id) {
let data = this.state.todos;
this.setState({
todos: data.filter((item, index) => {
if (item.id !== id) {
return item;
}
})
})
}
// 添加單條數據
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è)務組件我說一下我的理解:
- 展示組件:負責頁面的渲染,效果展示。其數據來源是業(yè)務組件傳遞過來的
props
,或者自身的state
,其處理函數都由業(yè)務組件定義的函數通過props
傳遞過來,在自身函數中與業(yè)務組件做數據交互。 - 業(yè)務組件: 負責與服務器做ajax請求、數據的獲取、業(yè)務邏輯的定義等業(yè)務交互。例如本案例的添加數據的函數,刪除數據的函數都是在TodoList組件定義好 ,傳遞給對應的子組件。而List列表的數據也是由這個組件傳遞過去的。
入口文件
// 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