React零基础入门到实战,完成企业级项目简书网站开发
第3章 React基础精讲
Dell
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值一定要放在循环的最外层元素上,否则是没有用的。