(06)React 入门——③ 实现 TodoList 新增、删除功能 | React 基础理论实操
转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
涉及面试题:
1. 在 JSX 中如何进行循环?
2. keys 是否需要全局唯一?
[编号:react_06]
1 新增
紧接上一篇的代码,我们需要实现需求:在页面 input 框里输入的内容,当点击“提交按钮”时,其内容会被依次放到下边的“列表项”里。
进入 TodoList.js
文件:
🔗前置知识:《JavaScript 基础——JS 数组:② ES5 数组方法》
《JavaScript 基础——JS 数组:① ES3 数组方法》
import React, { Component, Fragment } from "react";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: "",
list: ["qdywxs", "Oli", "React"] /*
3️⃣-⑤:接下来,我们为了演示效果,
在这里人为地写死一些内容。
*/
};
}
render() {
return(
<Fragment>
<div>
<input
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
{/*
1️⃣既然是点击“按钮”后才有的后续一系列事,那么首先,我们得给这个“按钮”绑定一个
“点击事件”;
*/}
<button onClick={this.handleBtnClick.bind(this)}>
提交
</button>
</div>
<ul>
{/*
3️⃣-①:页面显示的内容是由“数据”决定的,所以我们先把这里为了演示而编写的初始数据注释掉;
<li>React 初识</li>
<li>React 入门</li>
<li>React 进阶</li>
*/}
{/* 3️⃣-②:我们把上边的“数据”项 list 显示到这里来(通过 map 方法,将每一项予以列示);*/}
{
this.state.list.map((item, index) => { /*
3️⃣-③:回调函数会接收两个参数:
“每一项的内容 item”和“每一项对应的下标 index”;
*/
return( // 3️⃣-④:让它返回一个 li 标签,标签里展示的是“每一项的内容 item”;
<li>
{item}
</li>
)
})
}
</ul>
</Fragment>
)
}
handleInputChange(e) {
this.setState({
inputValue: e.target.value
})
}
// 2️⃣然后,我们在这里增加点击事件执行的方法;
handleBtnClick() {
// 3️⃣这个方法里应该是一个怎样的逻辑呢?
}
}
export default TodoList;
3️⃣-⑥:在页面查看效果(发现页面跟着变了);
3️⃣-⑦:既然如上图所示,效果出来了。我们需要去把 list 里边写死的内容清除掉,以便接下来的操作。
this.state = {
inputValue: "",
// list: ["qdywxs", "Oli", "React"]
list: []
};
4️⃣接下来我们实现——在页面 input 框里输入的内容,当点击“提交按钮”时,其内容会被依次放到下边的“列表项”里。
import React, { Component, Fragment } from "react";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: "",
list: []
};
}
render() {
return(
<Fragment>
<div>
<input
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button onClick={this.handleBtnClick.bind(this)}>
提交
</button>
</div>
<ul>
{
this.state.list.map((item, index) => {
return(
<li>
{item}
</li>
)
})
}
</ul>
</Fragment>
)
}
handleInputChange(e) {
this.setState({
inputValue: e.target.value
})
}
handleBtnClick() {
/*
4️⃣-①:执行的方法逻辑为——将“数据”项 inputValue 里的内容,放到“数据”项 list 里。
然后,只要“数据”项 list 里边有内容,页面就会自动变化;
*/
this.setState({
list: [...this.state.list, this.state.inputValue], /*
4️⃣-②:我们通过 ES6 语法,
把“新增的”和“之前的”合成一个新数组;
*/
inputValue: "" /*
4️⃣-③:同时,当输入的内容展现在页面时,
我们把 input 框里输入的历史内容删除掉。
*/
})
}
}
export default TodoList;
看看页面效果:
❌上图貌似完美实现了效果,但是是否有我们没有注意到的点呢? 答:有!
点开上图所在页面的控制台,我们发现了如下图所示的“警告”(不是“错误”,所以页面看起来好像一切很完美):
它提示我们:在 React 中,当你做循环渲染的时候,你需要给渲染出的每一项增加一个 key
值!这个 key
值是每一项唯一的“标识符”。
就目前知识储备而言,我们先用“下标 index
”作为 key
值——当然,实际编程中,使用 index
作为 key
值是一个很不好的习惯,后边我们会详讲,这里暂时不用太过关注。
import React, { Component, Fragment } from "react";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: "",
list: []
};
}
render() {
return(
<Fragment>
<div>
<input
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button onClick={this.handleBtnClick.bind(this)}>
提交
</button>
</div>
<ul>
{
this.state.list.map((item, index) => {
return(
<li key={index}> {/* 🚀给渲染出的每一项增加一个 key 值! */}
{item}
</li>
)
})
}
</ul>
</Fragment>
)
}
handleInputChange(e) {
this.setState({
inputValue: e.target.value
})
}
handleBtnClick() {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: ""
})
}
}
export default TodoList;
再次查看控制台,警告没有了:
2 删除
紧接上文代码,我们需要实现新的需求:点击“列表项”里的任一项,它就会从这个列表项里被删除。
import React, { Component, Fragment } from "react";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: "",
list: []
};
}
render() {
return(
<Fragment>
<div>
<input
value={this.state.inputValue}
onChange={this.handleInputChange.bind(this)}
/>
<button onClick={this.handleBtnClick.bind(this)}>
提交
</button>
</div>
<ul>
{
this.state.list.map((item, index) => {
return(
/*
1️⃣我们在生成 li 标签的时候,给每一个 li 标签绑定一个“点击”事件,
使其在被“点击”时,去执行 handleItemDelete 方法;
*/
/*
3️⃣-①:首先,我们把被“点击”的 li 的“下标”index
传给 handleItemDelete 方法;
*/
<li
key={index}
onClick={this.handleItemDelete.bind(this, index)}
>
{item}
</li>
)
})
}
</ul>
</Fragment>
)
}
handleInputChange(e) {
this.setState({
inputValue: e.target.value
})
}
handleBtnClick() {
this.setState({
list: [...this.state.list, this.state.inputValue],
inputValue: ""
})
}
// 2️⃣我们在这里写一个 handleItemDelete 方法;
handleItemDelete(index) { // 3️⃣-②:这里去接收到这个传递过来的“下标”;
// 3️⃣这个“删除”方法的逻辑为:
const list = [...this.state.list] /*
3️⃣-③:我定义一个常量等于一个“拷贝”的“数据”项 list;
❗️❗️❗️之所以这样做,是由于 React 中有一个概念叫 immutable,
它是指——state 不允许我们做任何的改变!因为它涉及到 React 性能
优化相关的问题!如果你想改变,你可以“拷贝”一个副本出来进行操作。
*/
list.splice(index, 1) /*
3️⃣-④:我们用 ES3 数组里的 splice 方法,将所“点击”项删除。
即,所“点击”项的下标为 index,然后从 index 开始,删除 1 项。
❗️splice 方法会破坏原数组,所以最后返回的是已经“删除”了某项的 list。
*/
this.setState({
list: list // 3️⃣-⑤:再调用 setState 方法,将“数据”项 list 变为上一步得到的 list。
}
)
}
}
export default TodoList;
看下页面效果:
祝好,qdywxs ♥ you!
转载自:https://juejin.cn/post/7251407757844398117