教程:井字棋游戏 – React 中文文档 📅 2025-07-10 07:16:14 ✍️ admin 👁️ 1811 ❤️ 871 当你在传递给 map 的函数中遍历 history 数组时,squares 参数遍历 history 的每个元素,move 参数遍历每个数组索引:0 、1、2……(在大多数情况下,你需要数组元素,但要渲染落子列表,你只需要索引。) 对于井字棋游戏历史中的每一步,你创建一个列表项 ,其中包含一个按钮 。该按钮有一个 onClick 处理程序,它调用一个名为 jumpTo 的函数(你尚未实现)。 现在,你应该会看到游戏中发生的动作列表和开发人员工具控制台中的错误。让我们讨论一下“关键”错误的含义。 选择 key 当你渲染一个列表时,React 会存储一些关于每个渲染列表项的信息。当你更新一个列表时,React 需要确定发生了什么变化。你可以添加、删除、重新排列或更新列表的项目。 想象一下从 Alexa: 7 tasks leftBen: 5 tasks left 到 Ben: 9 tasks leftClaudia: 8 tasks leftAlexa: 5 tasks left 除了更新的计数之外,阅读本文的人可能会说你交换了 Alexa 和 Ben 的顺序,并在 Alexa 和 Ben 之间插入了 Claudia。然而,React 是一个计算机程序,不知道你的意图,因此你需要为每个列表项指定一个 key 属性,以将每个列表项与其兄弟项区分开来。如果你的数据来自数据库,Alexa、Ben 和 Claudia 的数据库 ID 可以用作 key: {user.name}: {user.taskCount} tasks left 重新渲染列表时,React 获取每个列表项的 key 并搜索前一个列表的项以查找匹配的 key。如果当前列表有一个之前不存在的 key,React 会创建一个组件。如果当前列表缺少前一个列表中存在的 key,React 会销毁前一个组件。如果两个 key 匹配,则落子相应的组件。 key 告诉 React 每个组件的身份,这使得 React 可以在重新渲染时保持 state。如果组件的 key 发生变化,组件将被销毁,新 state 将重新创建。 key 是 React 中一个特殊的保留属性。创建元素时,React 提取 key 属性并将 key 直接存储在返回的元素上。尽管 key 看起来像是作为 props 传递的,但 React 会自动使用 key 来决定要更新哪些组件。组件无法询问其父组件指定的 key。 强烈建议你在构建动态列表时分配适当的 key。如果你没有合适的 key,你可能需要考虑重组你的数据,以便你这样做。 如果没有指定 key,React 会报错,默认使用数组索引作为 key。在尝试重新排序列表项或插入/删除列表项时,使用数组索引作为 key 是有问题的。显式传递 key={i} 可以消除错误,但与数组索引有相同的问题,在大多数情况下不推荐使用。 key 不需要是全局唯一的;它们只需要在组件及其同级组件之间是唯一的。 实现时间旅行 在井字棋游戏的历史中,过去的每一步都有一个唯一的 ID 与之相关联:它是动作的序号。落子永远不会被重新排序、删除或从中间插入,因此使用落子的索引作为 key 是安全的。 在 Game 函数中,你可以将 key 添加为 ,如果你重新加载渲染的游戏,React 的“key”错误应该会消失: const moves = history.map((squares, move) => { //... return ( jumpTo(move)}>{description} );});