(09)React 入门——⑥ TodoList 代码优化 | React 基础理论实操
转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
1 TodoItem.js
代码优化
之前的几篇文章,我们完整地做出了 TodoList 的相关功能。但由于讲解的需要,其中有一些代码并不符合“标准 React 编码规范”。
本篇我们对之前的代码进行一些“优化”。
打开 TodoItem.js
文件,需要优化的点:
- 为了“性能”,我们一般把与“this 指向绑定”相关的代码都统一放在
constructor
里边; - 能用 ES6 的地方,尽可能地用 ES6 语法(如本例中的“对象解构赋值”)。
🔗前置知识:《解构赋值:数组、对象、函数的解构赋值》
❎以下为原代码和“标记”的需要优化的地方:
import React, { Component } from "react";
class TodoItem extends Component {
render() {
return(
<div onClick={this.handleClick.bind(this)}> {/*
❎-①:我们一般把与“this 指向绑定”相关
的代码都统一放在 constructor 里边;
*/}
{this.props.content} {/* ❎-②:用 ES6 语法——对象的解构赋值; */}
</div>
)
}
handleClick() {
this.props.itemDelete(this.props.index) {/* ❎-③:同理,用 ES6 语法——对象的解构赋值。 */}
}
}
export default TodoItem;
✔️以下为“优化”后的代码:
import React, { Component } from "react";
class TodoItem extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
render() {
const {content} = this.props
return(
<div onClick={this.handleClick}>
{content}
</div>
)
}
handleClick() {
const {itemDelete, index} = this.props
itemDelete(index)
}
}
export default TodoItem;
2 TodoList.js
代码优化
打开 TodoList.js
文件,需要优化的点:
-
同理,为了“性能”,我们一般把与“this 指向绑定”相关的代码都统一放在
constructor
里边; -
JSX 中,我们一般放置的是页面上会显示的内容。因此,我们尽可能地不要在里边放很多“逻辑代码”,与“逻辑”相关的代码,我们直接提取出来用一个“方法”来表示;
-
新版 React 中,已经不推荐诸如下面的写法(传入对象的形式)来修改“数据”项了:
this.setState({
inputValue: e.target.value
})
取而代之的是,采用“传入函数”的形式来修改“数据”项。
❗️❗️❗️但要注意,采用这种“函数”的形式传入时,它会变成一个“异步”的 setState(我们后边讲“虚拟 DOM”时,会详细讲解为什么需要一个“异步”的 setState),我们要“显式”的在外层对 value
值进行保存,然后再在内层去使用它。否则会报错!
const value = e.target.value
this.setState(() => ({
inputValue: value
}))
-
setState
里边可以接受一个参数叫prevState
。-
prevState
指的是:修改数据之前时的state
是什么样的。所以,在代码中,遇到“修改数据之前时的state
”时(如this.state.list
),我们可以直接改写成prevState.list
; -
采用
prevState
的好处:它可以让我们避免由于不小心而去改动了state
的状态。
-
-
我们做“循环”时,要记得给“循环”的每一项添加一个“唯一”的
key
值。本例中,我们暂时用index
作为这个“唯一”的值。但index
作为key
值,是一种不好的方式,它很有可能会造成代码的报错。具体怎么才是最好的方式,待我们后边讲“虚拟 DOM”时,再详细讲解。
❎以下为原代码和“标记”的需要优化的地方:
import React, { Component, Fragment } from "react";
import TodoItem from "./TodoItem";
import "./style.css";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: "",
list: []
};
}
render() {
return(
<Fragment>
<div>
<label htmlFor="insertArea">请输入要进行的事项:</label>
<input
id="insertArea"
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)} {/*
❎-①:我们一般
把与“this 指向绑定”相关的代码
都统一放在 constructor 里边;
*/}
/>
<button onClick={this.handleBtnClick.bind(this)}> {/*
❎-②:我们一般
把与“this 指向绑定”相关的代码
都统一放在 constructor 里边;
*/}
提交
</button>
</div>
<ul>
{/* ❎-④:JSX 里,与“逻辑”相关的代码,我们要尽可能地抽离成“方法”! */}
{
this.state.list.map((item, index)=>{
return(
<TodoItem
content={item}
index={index}
itemDelete={this.handleItemDelete.bind(this)} {/*
❎-③:我们一般
把与“this 指向绑定”相关的代码
都统一放在 constructor 里边;
*/}
/>
)
})
}
</ul>
</Fragment>
)
}
handleInputChange(e) {
this.setState({ /*
❎-⑤:新版 React 提倡我们用“传入函数”的形式修改“数据项”;
用这种形式时,要注意先在外层对 value 值进行保存,然后才能在内层进行使用!
*/
inputValue: e.target.value
})
}
handleBtnClick() {
this.setState({ /*
❎-⑥:新版 React 提倡我们用“传入函数”的形式
修改“数据项”;
*/
list: [...this.state.list, this.state.inputValue], /*
❎-⑦:用 prevState 来代替
数据“修改前”的状态;
*/
inputValue: ""
})
}
handleItemDelete(index) {
const list = [...this.state.list] /*
❎-⑨:用 prevState 来代替
数据“修改前”的状态;
*/
list.splice(index, 1)
this.setState({ // ❎-⑧:新版 React 提倡我们用“传入函数”的形式修改“数据项”;
list: list
}
)
}
}
export default TodoList;
✔️以下为“优化”后的代码:
import React, { Component, Fragment } from "react";
import TodoItem from "./TodoItem";
import "./style.css";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: "",
list: []
};
this.handleInputChange = this.handleInputChange.bind(this);
this.handleBtnClick = this.handleBtnClick.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
}
render() {
return(
<Fragment>
<div>
<label htmlFor="insertArea">请输入要进行的事项:</label>
<input
id="insertArea"
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange}
/>
<button onClick={this.handleBtnClick}>
提交
</button>
</div>
<ul>
{this.getTodoItem()}
</ul>
</Fragment>
)
}
getTodoItem() {
return this.state.list.map((item, index) => {
return(
<TodoItem
key={index}
content={item}
index={index}
itemDelete={this.handleItemDelete}
/>
)
})
}
handleInputChange(e) {
const value = e.target.value
this.setState(() => ({
inputValue: value
}))
}
handleBtnClick() {
this.setState((prevState) => ({
list: [...prevState.list, prevState.inputValue],
inputValue: ""
}))
}
handleItemDelete(index) {
this.setState((prevState) => {
const list = [...prevState.list]
list.splice(index, 1)
return {list}
})
}
}
export default TodoList;
最后看看页面效果(没“报错”、没“警告”):
祝好,qdywxs ♥ you!
转载自:https://juejin.cn/post/7270916734139514880