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

JavaScript元素点击次数统计及表格单元格状态切换方案咨询

问题描述

我现在有一个表格和JavaScript函数,实现了点击表格单元格时,该行其他单元格隐藏,被点击单元格移至表格行最左侧,同时右侧滑出信息的效果。但我希望再次点击时,所有内容恢复至初始状态。

我想了解JavaScript是否可以追踪用户对元素的点击次数,计划通过奇数次点击执行隐藏、移动操作,偶数次点击恢复初始状态,不确定是否可行,或者有没有更优的恢复初始状态的实现方案。


现有代码

HTML

<table id='TrendGames'>
    <tbody>
        <tr>
                <td id="cell1"> Cell 1
                <img class='GameCover' src='.png' alt="cell1" />
                </td>
                <td id="cell2">Cell 2
                <img class='GameCover' src='.png' alt="cell2" />
                </td>
                <td id="cell31">Cell 3
                <img class='GameCover' src='.png' alt="cell3" />
                </td>
                <td id="cell4">Cell 4
                <img class='GameCover' src='.png' alt="cell4" />
                </td>
        </tr>
       </tbody>
</table>

JavaScript

document.addEventListener('DOMContentLoaded', function() {
  var table = document.getElementById('TrendGames');
  table.addEventListener('click', function(event) {
    var clickedCell = event.target.closest('td');
    if (clickedCell) {
      handleCellClick(clickedCell);
    }
  });
});

function handleCellClick(clickedCell) {
  var row = clickedCell.parentElement;
  var cells = row.children;

  // Hide other cells and rearrange the clicked cell
  for (var i = 0; i < cells.length; i++) {
    if (cells[i] !== clickedCell) {
      cells[i].style.display = 'none';
    }
  }
  row.insertBefore(clickedCell, row.firstChild); // Move to the leftmost
  clickedCell.colSpan = cells.length
  // Open the slider and display information
  openSlider(clickedCell);
}

function openSlider(cell) {
  // Implement the slider logic here
  console.log(cell.id)
}

实现方案

思路1:用自定义属性追踪点击次数

可以给单元格添加自定义属性(比如data-click-count)记录点击次数,每次点击后更新计数,根据奇偶性执行不同操作。这种方式简单直接,但需注意用户点击其他单元格时要重置之前的状态。

修改后的代码示例:

document.addEventListener('DOMContentLoaded', function() {
  var table = document.getElementById('TrendGames');
  table.addEventListener('click', function(event) {
    var clickedCell = event.target.closest('td');
    if (clickedCell) {
      handleCellClick(clickedCell);
    }
  });
});

function handleCellClick(clickedCell) {
  var row = clickedCell.parentElement;
  var cells = row.children;
  // 获取当前点击次数,默认0
  var clickCount = parseInt(clickedCell.getAttribute('data-click-count')) || 0;
  clickCount++;
  clickedCell.setAttribute('data-click-count', clickCount);

  if (clickCount % 2 === 1) {
    // 奇数次点击:执行展开操作
    for (var i = 0; i < cells.length; i++) {
      if (cells[i] !== clickedCell) {
        cells[i].style.display = 'none';
      }
    }
    // 记录原始位置,方便恢复
    clickedCell.dataset.originalIndex = Array.from(cells).indexOf(clickedCell);
    row.insertBefore(clickedCell, row.firstChild);
    clickedCell.colSpan = cells.length;
    openSlider(clickedCell);
  } else {
    // 偶数次点击:恢复初始状态
    resetRowState(row);
    closeSlider();
  }
}

// 重置行的初始状态
function resetRowState(row) {
  var cells = row.children;
  // 恢复所有单元格显示
  for (var i = 0; i < cells.length; i++) {
    cells[i].style.display = '';
    cells[i].colSpan = 1;
    // 重置点击计数
    cells[i].removeAttribute('data-click-count');
  }
  // 按原始顺序重新排列单元格
  var sortedCells = Array.from(cells).sort((a, b) => {
    return parseInt(a.dataset.originalIndex || 0) - parseInt(b.dataset.originalIndex || 0);
  });
  sortedCells.forEach(cell => row.appendChild(cell));
  // 移除原始位置标记
  sortedCells.forEach(cell => cell.removeAttribute('data-original-index'));
}

function openSlider(cell) {
  // 实现滑块展开逻辑
  console.log('打开滑块:', cell.id);
}

function closeSlider() {
  // 实现滑块关闭逻辑
  console.log('关闭滑块');
}

思路2:通过状态标记判断当前模式(更优)

比起追踪点击次数,直接判断当前行是否处于「展开状态」更可靠——给行或单元格添加data-expanded属性,或者记录当前展开的单元格。这种方式能自动处理跨单元格点击的场景,避免计数混乱。

优化后的代码示例:

document.addEventListener('DOMContentLoaded', function() {
  var table = document.getElementById('TrendGames');
  table.addEventListener('click', function(event) {
    var clickedCell = event.target.closest('td');
    if (clickedCell) {
      handleCellClick(clickedCell);
    }
  });
});

function handleCellClick(clickedCell) {
  var row = clickedCell.parentElement;
  var cells = row.children;
  var expandedCell = row.querySelector('[data-expanded]');

  if (!expandedCell || expandedCell !== clickedCell) {
    // 无展开状态或点击的不是当前展开单元格:执行展开
    // 先重置之前的状态(如果有)
    if (expandedCell) {
      resetRowState(row);
    }
    // 记录原始位置
    clickedCell.dataset.originalIndex = Array.from(cells).indexOf(clickedCell);
    clickedCell.dataset.expanded = 'true';
    // 隐藏其他单元格
    for (var i = 0; i < cells.length; i++) {
      if (cells[i] !== clickedCell) {
        cells[i].style.display = 'none';
      }
    }
    row.insertBefore(clickedCell, row.firstChild);
    clickedCell.colSpan = cells.length;
    openSlider(clickedCell);
  } else {
    // 点击的是当前展开单元格:恢复初始状态
    resetRowState(row);
    closeSlider();
  }
}

function resetRowState(row) {
  var cells = row.children;
  // 恢复所有单元格显示和属性
  Array.from(cells).forEach(cell => {
    cell.style.display = '';
    cell.colSpan = 1;
    cell.removeAttribute('data-expanded');
    cell.removeAttribute('data-original-index');
  });
  // 按原始顺序重新排列
  var sortedCells = Array.from(cells).sort((a, b) => {
    return parseInt(a.dataset.originalIndex || Array.from(cells).indexOf(a)) - 
           parseInt(b.dataset.originalIndex || Array.from(cells).indexOf(b));
  });
  sortedCells.forEach(cell => row.appendChild(cell));
}

function openSlider(cell) {
  console.log('打开滑块:', cell.id);
}

function closeSlider() {
  console.log('关闭滑块');
}

方案优势对比

  • 思路1适合单一单元格的独立切换,但需额外处理跨单元格点击的状态重置,否则会出现多个单元格同时计数的问题。
  • 思路2更健壮,能自动处理跨单元格点击场景,符合用户直觉操作,是更优的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 21:29:54