考虑这个简单的react组件以显示列表。
class List extends React.Component{
constructor(props){
super(props)
this.data = ["abvjx", "sda", "fdsaf"]
}
getRows(){
return this.data.map((el, index)=>{
return (
<li>
{el}
<button onClick={()=>{alert(index)}}>Click
</button>
</li>
);
})
}
getRows2(){
let ret = []
let i = 0
for (const row of this.data){
ret.push(
<li>{row, i}
<button onClick={()=>{alert(i)}}>Click</button>
</li>);
i++;
}
return ret
}
render(){
return (
this.getRows2()
)
}
}
ReactDOM.render(<List />, document.getElementById("container"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="container"></div>
getRows()
返回一个jsx元素数组,显示数据数组中的元素及其索引,每行还具有一个按钮,单击该按钮将显示一个弹出窗口,此弹出窗口显示该行的索引。 / p>
getRows2()
的功能相同,只是这次我使用for
而不是Array.map
循环。
但是当我使用getRows2()
时单击任何按钮时,弹出窗口始终显示3,而getRows()
在弹出窗口中显示正确的索引
答案 0 :(得分:1)
很简单,您基本上在其最后一个索引上使用i
。
这里:
let i = 0
for (let row of this.data){
ret.push(
<li>{row, i}
<button onClick={()=>{alert(i)}}>Click</button>
</li>);
i++;
}
// Since you've been incrementing i within the loop.. any call after the loop to use i is when i=3
这里发生的是您向onClick
注册了一个alert(i)
事件。但是我独立于循环中的每个项目。 i
在循环外部定义。因此,在执行click事件时,它是在呈现按钮之后,此时i
已经在i = 3
处了……请记住,您在循环的每个项目上都对其进行了递增。因此它一直显示3。
您可以使用的一种方法是尝试并使用data-*
属性存储i
。您可以按照以下方式进行操作:
class List extends React.Component{
constructor(props){
super(props)
this.data = ["abvjx", "sda", "fdsaf"]
}
getRows(){
return this.data.map((el, index)=>{
return (
<li>
{el}
<button onClick={()=>{alert(index)}}>Click
</button>
</li>
);
})
}
getRows2(){
let ret = []
let i = 0
for (const row of this.data){
ret.push(
<li>{row, i}
<button data-i={i} onClick={
(e) => alert(e.target.getAttribute("data-i"))
}
>Click</button>
</li>);
i++;
}
return ret
}
render(){
return (
this.getRows2()
)
}
}
ReactDOM.render(<List />, document.getElementById("container"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="container"></div>
答案 1 :(得分:0)
发生这种情况是在调用i
函数之前更新alert
的值。
这是称为关闭的概念。
用MDN话
闭包是捆绑在一起(封闭)的函数和对其周围状态(词汇环境)的引用的组合。换句话说,闭包使您可以从内部函数访问外部函数的作用域。在JavaScript中,每次创建函数时都会在函数创建时创建闭包。
MDN :https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
Eric Elliot 给出了一个很好的解释:https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-closure-b2f0d2152b36
答案 2 :(得分:-1)
You can't push a JSX element inside an array
。
这段代码是完全错误的:
getRows2(){
let ret = []
let i = 0
for (const row of this.data){ ret.push(<li>{row, i}<button onClick={()=>{alert(i)}}>Click</button></li>) i++; }
return ret
}
您需要这样清除代码:
render(){
return (
<ul>
{this.data.map((el, index)=>{
return (<li>{el}<button onClick={()=>{alert(index)}}>Click</button></li>) })
}
</ul>
)
}