如何让CSS Grid周历的空白单元格可点击并获取时间与星期?
解决方案
方法一:事件委托+坐标计算获取时间与星期
直接在最外层Grid容器上绑定点击事件,通过点击位置的坐标计算出对应的星期和时间:
- 给最外层的
.grid.flex-auto容器添加onClick事件监听 - 点击时通过
getBoundingClientRect()获取容器与点击点的坐标关系,分别计算行列索引,映射到具体的星期和时间
示例代码(React环境):
const handleCalendarClick = (e) => { const gridContainer = e.currentTarget; const rect = gridContainer.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; // 计算星期:按7列划分,根据水平占比确定列索引 const colIndex = Math.floor((x / rect.width) * 7); const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; // 可根据你的列顺序调整 const targetDay = weekDays[colIndex]; // 计算时间:按48行(每半小时一行)划分,转换为具体时间格式 const rowIndex = Math.floor((y / rect.height) * 48); const hour = Math.floor(rowIndex / 2); const minute = rowIndex % 2 === 0 ? '00' : '30'; const period = hour < 12 ? 'AM' : 'PM'; const displayHour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour; const targetTime = `${displayHour}:${minute} ${period}`; // 打开Dialog并传入数据 // openDialog({ day: targetDay, time: targetTime }); }; // 绑定事件到最外层容器 <div className="grid flex-auto grid-cols-1 grid-rows-1" onClick={handleCalendarClick}> {/* 原有周历结构 */} </div>
方法二:重构单元格结构,携带数据属性
重新构建一个覆盖整个周历的单元格网格,每个空白单元格通过data-*属性直接存储对应的星期和时间,点击时直接读取:
- 生成7列×48行的单元格网格,每个单元格对应一个时间点+星期组合
- 给每个单元格添加
data-day和data-time属性,绑定点击事件读取数据
示例代码(React环境):
// 生成时间槽数据:48条对应24小时的每半小时 const timeSlots = Array.from({ length: 48 }, (_, i) => { const hour = Math.floor(i / 2); const minute = i % 2 === 0 ? '00' : '30'; const period = hour < 12 ? 'AM' : 'PM'; const displayHour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour; return `${displayHour}:${minute} ${period}`; }); const weekDays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; const handleCellClick = (e) => { const targetDay = e.target.dataset.day; const targetTime = e.target.dataset.time; // 打开Dialog并传入数据 // openDialog({ day: targetDay, time: targetTime }); }; // 渲染覆盖式单元格网格,放在原有结构同一层级 <div className="col-start-1 col-end-2 row-start-1 grid grid-cols-7 grid-rows-48"> {weekDays.map((day, colIdx) => ( timeSlots.map((time, rowIdx) => ( <div key={`${colIdx}-${rowIdx}`} className="cursor-pointer" data-day={day} data-time={time} onClick={handleCellClick} /> )) ))} </div>
注意事项
- 方法一要注意容器尺寸计算的准确性,避免滚动、缩放导致坐标偏差
- 方法二的单元格网格需设置合适的层级,避免遮挡原有事件组件的交互
- 可根据你的周历星期起始顺序,调整
weekDays数组的排列
内容的提问来源于stack exchange,提问作者FailedUnitTest
相关产品推荐
相关产品推荐

