本章内容
上一节内容续使用 ”TodoList“ 案例来讲解一下”组件拆分与组件传值“。观察里面的代码,发现有优化的地方很多。本节我们针对其中代码进行优化
打开
TodoItem.js
,我们需要优化的点有
为了”性能“,我们统一把与 this
绑定相关的代码都统一放到 constructor
中
尽量是用 ES6
的语法(例如 TodoItem.js
中可以用到 ES6
的”结构赋值“)
下面来标记下需要优化的点
// 优化前代码
import React, { Component } from 'react'
class TodoItem extends Component {
render () {
return (
// 优化点:把与 this 相关绑定的代码统一放到 constructor 中
<div onClick={this.handleClick.bind(this)}>
{/* 优化点:使用 ES6 的解构赋值 */}
{this.props.content}
</div>
)
}
handleClick() {
// 优化点:使用 ES6 的解构赋值
this.props.deleteFn(this.props.index)
}
}
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 (
// 优化点:把与 this 相关绑定的代码统一放到 constructor 中
<div onClick={this.handleClick}>
{/* 优化点:使用 ES6 的解构赋值 */}
{content}
</div>
)
}
handleClick() {
const { deleteFn, index } = this.props
// 优化点:使用 ES6 的解构赋值
deleteFn(index)
}
}
export default TodoItem
打开
TodoList.js
,我们需要优化的点有:
同上,为了”性能“,我们统一把与 this
绑定相关的代码都统一放到 constructor
中
JSX 中我们尽量只放页面显示的内容,逻辑代码尽量抽出来一个方法
涉及”循环渲染列表“时,记得给每个循环的每一项添加 key
值,现在暂时用 index
(当然这是一种不好的方式,可能造成代码报错,具体好的方式等我们讲”虚拟DOM“时再补充)
新版 React
已经不推荐使用 this.setState({xxx: xxx})
的方式来修改数据了,取而代之的是”传入函数“的形式进行.
注意:
1、使用”函数“的形式去更改数据时,要注意的是,它会变成一个”异步“的 setState
(后面讲 ”虚拟DOM“ 时再详细说一下为什么是需要”异步“),我们要”显示“的在外层对 value
值进行保存,然后再在内层去使用它,否则报错
2、setState
函数接受一个prevState
参数,指的是修改数据前的 state
是什么样的。所以在代码中,遇到”修改数据之前的 state
“时(如:this.state.list
),可以直接写成 prevState.list
3、使用 prevState
的好处是可以避免不小心改动到了 state
的状态
const value = e.target.value
this.setState(() => {
inputValue: value
})
import React, { Component, Fragment } from "react";
import TodoItem from "./TodoItem";
class TodoList extends Component{
constructor(props) {
super(props)
this.state = {
inputValue: '',
list: []
}
}
render() {
return (
<Fragment>
<div>
{/* this 的绑定同一放在 contructor 中 */}
<input value={this.state.inputValue} onChange={this.changeInputValue.bind(this)} />
{/* this 的绑定同一放在 contructor 中 */}
<button onClick={this.addListData.bind(this)}> 提交 </button>
</div>
<ul>
{/* JSX 中的逻辑代码尽量抽取成”方法“ */}
{this.state.list.map((item, index) => {
return (
// this 的绑定同一放在 contructor 中
<TodoItem content={item} index={index} deleteFn={this.deleteData.bind(this)}></TodoItem>
)
})}
</ul>
</Fragment>
)
}
deleteData(index) {
const list = [...this.state.list]
list.splice(index, 1)
// 改用新版 React 推荐的”函数“形式来变更数据
this.setState({
list: list
})
}
addListData() {
// 改用新版 React 推荐的”函数“形式来变更数据
this.setState({
list: [...this.state.list, this.state.inputValue]
})
// 改用新版 React 推荐的”函数“形式来变更数据
this.setState({
inputValue: ''
})
}
changeInputValue(e) {
// 改用新版 React 推荐的”函数“形式来变更数据
this.setState({
inputValue: e.target.value
})
}
}
export default TodoList
import React, { Component, Fragment } from "react";
import TodoItem from "./TodoItem";
class TodoList extends Component{
constructor(props) {
super(props)
this.deleteData = this.deleteData.bind(this)
this.addListData = this.addListData.bind(this)
this.changeInputValue = this.changeInputValue.bind(this)
this.state = {
inputValue: '',
list: []
}
}
render() {
return (
<Fragment>
<div>
<input value={this.state.inputValue} onChange={this.changeInputValue} />
<button onClick={this.addListData}> 提交 </button>
</div>
<ul> {this.getTodoItem()} </ul>
</Fragment>
)
}
getTodoItem() {
return this.state.list.map((item, index) => {
return <TodoItem key={index} content={item} index={index} deleteFn={this.deleteData}></TodoItem>
})
}
deleteData(index) {
this.setState((prevState) => {
const list = [...prevState.list]
list.splice(index, 1)
return {list}
})
}
addListData() {
this.setState((prevState) => ({
list: [...prevState.list, prevState.inputValue],
inputValue: ''
}))
}
changeInputValue(e) {
const value = e.target.value
this.setState(() => ({inputValue: value}))
}
}
export default TodoList
到此,本章内容结束!