You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何按组件点击顺序而非标识符排序数组?React开发咨询

解决方案:追踪点击顺序并据此排序组件数组

你的核心问题在于:当前arrMiniDices是直接遍历原listDices数组生成的,严格遵循原数组的id顺序,完全没考虑用户的点击行为。要实现按点击顺序排列,关键是先记录用户的点击顺序,再根据这个顺序来排序生成组件的数组。

下面是具体的分步解决方案:

1. 维护一个记录点击顺序的状态

首先在组件中添加状态,专门存储用户点击骰子的id顺序。

类组件示例:

class YourComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      listDices: [ {value: 1, hidden: false, id:0}, {value: 2, hidden: false, id:1}, {value: 6, hidden: false, id:2}, {value: 6, hidden: false, id:3}, {value: 5, hidden: false, id:4} ],
      clickedOrder: [] // 存储点击的id顺序
    };
  }
  // 其他方法...
}

函数组件示例:

const YourComponent = () => {
  const [listDices, setListDices] = useState([ {value: 1, hidden: false, id:0}, {value: 2, hidden: false, id:1}, {value: 6, hidden: false, id:2}, {value: 6, hidden: false, id:3}, {value: 5, hidden: false, id:4} ]);
  const [clickedOrder, setClickedOrder] = useState([]);
  // 其他逻辑...
};

2. 更新点击事件处理函数,维护点击顺序

修改handleHideDice方法,在切换骰子hidden状态的同时,同步更新点击顺序:

  • 当骰子从显示切换为隐藏(加入arrMiniDices):如果该id已在顺序中,先移除再追加到末尾(保证最新点击的排在最后);如果不在,直接追加。
  • 当骰子从隐藏切换为显示(移出arrMiniDices):从顺序中移除对应id。

类组件示例:

handleHideDice = (id) => {
  // 先更新骰子的hidden状态
  this.setState(prevState => ({
    listDices: prevState.listDices.map(item => 
      item.id === id ? {...item, hidden: !item.hidden} : item
    )
  }), () => {
    // 状态更新完成后处理点击顺序
    const targetDice = this.state.listDices.find(item => item.id === id);
    this.setState(prevState => {
      let newClickedOrder = [...prevState.clickedOrder];
      if (targetDice.hidden) {
        // 隐藏状态:移到顺序末尾或新增
        const existingIndex = newClickedOrder.indexOf(id);
        if (existingIndex !== -1) newClickedOrder.splice(existingIndex, 1);
        newClickedOrder.push(id);
      } else {
        // 显示状态:从顺序中移除
        const existingIndex = newClickedOrder.indexOf(id);
        if (existingIndex !== -1) newClickedOrder.splice(existingIndex, 1);
      }
      return { clickedOrder: newClickedOrder };
    });
  });
};

函数组件示例(结合useEffect处理异步状态):

const handleHideDice = (id) => {
  setListDices(prev => prev.map(item => 
    item.id === id ? {...item, hidden: !item.hidden} : item
  ));
};

// 监听listDices变化,同步更新点击顺序
useEffect(() => {
  const updatedDice = listDices.find(item => item.id === id);
  if (!updatedDice) return;

  setClickedOrder(prev => {
    let newOrder = [...prev];
    if (updatedDice.hidden) {
      const idx = newOrder.indexOf(updatedDice.id);
      if (idx !== -1) newOrder.splice(idx, 1);
      newOrder.push(updatedDice.id);
    } else {
      const idx = newOrder.indexOf(updatedDice.id);
      if (idx !== -1) newOrder.splice(idx, 1);
    }
    return newOrder;
  });
}, [listDices, id]);

3. 根据点击顺序生成arrMiniDices

不再直接遍历原数组,先过滤出hidden为true的骰子,再根据clickedOrder的顺序排序,最后生成组件:

// 类组件中
const { listDices, clickedOrder } = this.state;
const hiddenDices = listDices.filter(item => item.hidden);
const arrMiniDices = hiddenDices.sort((a, b) => {
  // 按clickedOrder中的索引排序,索引越小越靠前
  return clickedOrder.indexOf(a.id) - clickedOrder.indexOf(b.id);
}).map(item => (
  <BtnDice 
    key={item.id} 
    value={item.value} 
    className="btn__dice--small" 
    onClick={() => this.handleHideDice(item.id)} 
  />
));

// 函数组件逻辑完全一致,仅需替换为对应状态和方法

4. 初始化点击顺序(可选)

如果初始listDices中有已隐藏的骰子,需要在组件挂载时初始化clickedOrder,保证这些初始项按原顺序排列:
类组件:

componentDidMount() {
  const initialOrder = this.state.listDices
    .filter(item => item.hidden)
    .map(item => item.id);
  this.setState({ clickedOrder: initialOrder });
}

函数组件:

useEffect(() => {
  const initialOrder = listDices.filter(item => item.hidden).map(item => item.id);
  setClickedOrder(initialOrder);
}, []);

这样调整后,当你按d(id3) → b(id1) → c(id2) → a(id0) → e(id4)的顺序点击时,arrMiniDices就会严格按照这个点击顺序生成组件数组,完全符合你的预期。

内容的提问来源于stack exchange,提问作者yoan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:36:43