课程名称
课程章节
第3章 React基础精讲
- 3-6 TodoList 代码优化
课程讲师
课程内容
- TodoList代码优化
- 用es6的解构赋值语法,直接取props对应属性
- 先引入组件,再引入样式
- bind函数写在render中会影响很多性能,一般建议把this指向的绑定写在构造函数中。
- React标签的属性较多,可以用回车将其隔开。
- 代码过长的话,进行函数拆分
- 新版setState接收一个函数,而不是一个对象了,该函数需要有一个返回值,返回这个需要改变的对象。
- prevState参数的使用
- 注意:key值一定要放在循环的最外层元素上,否则是没有用的。
课程收获
TodoList代码优化
render(){
return(
<div onClick={this.handleClick}>{this.props.content}</div>
)
}
handleClick(){
this.props.deleteItem(this.props.index);
}
可以用es6的解构赋值语法,直接取props对应属性
render(){
const {content} = this.props;
return(
<div onClick={this.handleClick}>
{content}
</div>
)
}
handleClick(){
const {deleteItem,index} = this.props;
deleteItem(index);
}
一般情况下时先引入组件,再引入样式
import React, { Component, Fragment } from "react";
import TodoItem from "./TodoItem"
import "./style.css"
● bind函数写在render中会影响很多性能,一般建议把this指向的绑定写在构造函数中。
● 比如input的属性较多,可以用回车将其隔开。
● jsx其实展示的就是页面的内容,这里写了js的map语法,实际这里又融合了一些逻辑,这样致使jsx看起来非常长,一般可以再写一个方法,getTodoItem,将这块放入,然后替换成方法即可。这样jsx里面内容就很精简了。
● 注意:当在代码中,写得一坨一坨的时候,就可以做函数和代码上的拆分了。
TodoList
<Fragment>
<div>
{/* 下面是一个input框 */}
{
// 下面是一个input框
}
<label htmlFor="InputArea">输入内容</label>
<input
id="InputArea"
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
></input>
<button onClick={this.handleBtnClick.bind(this)}>提交</button>
</div>
<ul>
{
this.state.list.map((item,index) => {
// return <li
// key={index}
// onClick={this.handleDelItem.bind(this, index)}
// dangerouslySetInnerHTML={{__html:item}}
// ></li>
return <TodoItem
content = {item}
index = {index}
deleteItem = {this.handleDelItem.bind(this)}
/>
})
}
</ul>
</Fragment>
=>
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.handleDelItem = this.handleDelItem.bind(this)
}
render(){
return (
<Fragment>
<div>
{/* 下面是一个input框 */}
{
// 下面是一个input框
}
<label htmlFor="InputArea">输入内容</label>
<input
id="InputArea"
className="input"
value={this.state.inputValue}
onChange={this.handleInputChange}
></input>
<button onClick={this.handleBtnClick}>提交</button>
</div>
<ul>
{this.getTodoItem()}
</ul>
</Fragment>
)
}
handleInputChange(e){
this.setState({
inputValue: e.target.value
})
}
handleBtnClick(){
this.setState({
list:[...this.state.list, this.state.inputValue],
inputValue:""
})
}
handleDelItem(index){
const dest = [...this.state.list];
dest.splice(index, 1);
this.setState({
list: dest
})
}
getTodoItem(){
return this.state.list.map((item,index) => {
return <TodoItem
content = {item}
index = {index}
deleteItem = {this.handleDelItem}
/>
})
}
}
export default TodoList;
我们这里setState都是使用对象的方式进行数据变更,但是新版本中已经不推荐此写法了。
新版setState接收一个函数,而不是一个对象了,该函数需要有一个返回值,返回这个需要改变的对象。
handleInputChange(e){
this.setState(() => {
return {
inputValue: e.target.value
}
})
// this.setState({
// inputValue: e.target.value
// })
}
还可es6简写 => 不要return了,直接一个小括号即可。
this.setState(() => ({inputValue: e.target.value}))
老版本输入input可能会报错,那是因为setState传递一个函数,setState实际是异步的,应当先将获取的e.target.value保存为一个临时变量,然后再在异步函数中使用。
handleInputChange(e){
const value = e.target.value;
this.setState(() => ({inputValue: value}))
}
实际setState传递一个函数,它里有一个参数为prevState,代表修改数据之前的那一次的数据,它其实就等价于this.state。
handleBtnClick(){
this.setState(()=>({
list:[...this.state.list, this.state.inputValue],
inputValue:""
}))
// this.setState({
// list:[...this.state.list, this.state.inputValue],
// inputValue:""
// })
}
等价于:
handleBtnClick(){
this.setState((prevState)=>({
list:[...prevState.list, prevState.inputValue],
inputValue:""
}))
}
其实这种写法更靠谱,避免修改state的状态。
handleDelItem(index){
this.setState((prevState) => {
const list = [...prevState.list];
list.splice(index, 1);
return {list}
})
// const dest = [...this.state.list];
// dest.splice(index, 1);
// this.setState({
// list: dest
// })
}
解决key值的问题:key值暂时定为index,实际当前index在数组中是唯一的。
getTodoItem(){
return this.state.list.map((item,index) => {
return <TodoItem
key={index}
content = {item}
index = {index}
deleteItem = {this.handleDelItem}
/>
})
}
注意:key值一定要放在循环的最外层元素上,否则是没有用的。