我从事响应工作已经一年多了。我主要是使用.map,.forEach,.filter或如果对象是Object.keys和Object.values来迭代数组。
但是向jsx元素添加唯一键的不同方法是什么。到目前为止,我已经习惯了以下内容
使用数据中的唯一ID作为关键 Prop 的关键:
const data= [{"id": "01", "name": "abc"}, {"id": "02", "name": "xyz"}];
render(){
const items = data.map(item => {
return <span key={item.id}>{item.name}</span>;
}
return(
<div>
{items}
</div>
)
}
使用索引作为关键 Prop 的关键:
const data= [{"id": "01", "name": "abc"}, {"id": "02", "name": "xyz"}];
render(){
const items = data.map((item, i) => {
let keyValue = i+1;
return <span key={keyValue}>{item.name}</span>;
}
return(
<div>
{items}
</div>
)
}
除了我上面提到的方法之外,还有没有其他方法可以向jsx元素添加唯一键,并且最有效和推荐的方法是?
最佳答案
首先,避免使用随机键。
编写密钥的方法有很多,有些方法的性能会更好。
要了解我们选择的密钥如何影响性能,有必要了解React的对帐算法。
https://reactjs.org/docs/reconciliation.html
tl; dr引入了一种启发式方法,用于比较虚拟DOM树与该VDOM树的n个节点进行比较O(n)。这种启发式方法可以分为以下几点:
<Button />
到<NotButton />
),则会导致我们的按钮也要与其子级一起卸载,NotButton也要与其子级一起卸载。 现在假设我们有这个:
<div>
<Button title="One" />
<Button title="Two" />
</div>
我们想在下一个渲染中向DOM中添加一个Button,例如
<div>
<Button title="Zero" />
<Button title="One" />
<Button title="Two" />
</div>
该算法将如下所示:
<divs>
。由于它们具有相同的类型,因此我们无需重新创建新树。 Prop 是相同的,因此此时没有更改可应用于DOM。 One
与Zero
进行比较。协调者检测到这里是 Prop 变更,然后使用此标题更新DOM。 Two
与One
进行比较。协调器还会在此处检测 Prop 更改,并使用DOM编写此更改。 Button
被添加为最后一个 child ,因此在VDOM上创建了一个新的Button
实例,并将此更改写入DOM。 请注意,它们在DOM上有很多操作,因为它按索引比较组件。
现在,我们可以通过告知协调器这些实例应被重用来解决此问题。现在,让我们有这个:
<div>
<Button title="One" key="One" />
<Button title="Two" key="Two" />
</div>
我们想在下一个渲染中向DOM中添加一个Button,例如
<div>
<Button title="Zero" key="Zero" />
<Button title="One" key="One" />
<Button title="Two" key"Two" />
</div>
该算法将如下所示:
<divs>
。由于它们具有相同的类型,因此我们无需重新创建新树。 Prop 是相同的,因此此时没有更改可应用于DOM。 Button
。 “并且有 key ”(“一个”)。然后,在新的子代列表中寻找密钥相同的子代。 “哦,我遇到了!”但协调器意识到的 Prop 没有变化。这样,就不需要DOM操作了。 Button
也会发生相同的情况,它将通过keys
而不是index
进行比较。意识到它是同一个实例,并且没有更改 Prop ,因此React决定不在DOM上应用更改。 Button
,由于不存在具有相同键的子级,因此意识到应该在VDOM上创建实例,并且此更改应写在DOM上。 因此,通过可预测的内容使用密钥有助于协调器在DOM上执行较少的操作。健康键是可以从要映射的对象推断出来的键,例如
name
,id
或url
(如果我们将urls
转换为<imgs />
)。那
key=index
呢?将没有任何作用,因为默认情况下,协调器会按位置(即其索引)进行比较。这些键应该是全局唯一的吗?不必要。这些在 sibling 之间应该是唯一的,因此协调程序可以在节点的子节点进行迭代时区分它们。
随 secret 钥呢?应不惜一切代价避免这些情况。如果每个渲染上都有一个键更改,这将使React破坏并在VDOM上创建实例(并因此在DOM上进行额外的写操作),因为在新的子级中没有找到带有键的组件,而是一个新的具有相同的类型。
如果渲染输出像
<div>
<Button key={randomGenerator()} />
</div>
然后,每次执行
render
时(例如,由于 Prop /状态更改,或者即使重新渲染其父级并且我们的shouldComponentUpdate
返回true
),也会生成一个新的randomGenerator()
密钥。这将像:'嘿!我找到了带有
Button
键的F67BMkd==
,但是在下一个中没有找到。我将其删除。'哦!我遇到了带有
Button
键的SHDSA++5
!让我们创建一个新的。每当协调程序告知应删除和卸载实例时,其内部状态都会丢失;即使我们再次安装它。
在这种情况下,将不会保留VDOM上的实例。
Button
是相同的,但是协调器在DOM上一团糟。希望能帮助到你。
关于javascript - 在React循环中向JSX元素添加 key 的不同方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52196127/