React中使用Moment.js结合按钮按日期范围过滤对象数组
解决方案
你的方向是对的,核心是通过Moment.js计算时间阈值,再用这个阈值过滤数据。关键要保留原始数据,避免筛选后无法重置。下面分两种常见场景给出实现:
原生JavaScript实现
- 先保存原始数据,防止筛选后丢失源数据:
// 原始数据,不要直接修改 const originalData = [ {date: '2023-01-22', score: 57.675}, {date: '2022-11-05', score: 60.675}, {date: '2022-12-11', score: 78.675}, {date: '2022-08-26', score: 81.675} ]; // 用于展示的筛选后数据 let filteredData = [...originalData];
- 编写通用筛选函数,接收月数参数:
function filterDataByMonths(months) { // 计算指定月数前的起始日期(当天零点) const startDate = moment().startOf('day').subtract(months, 'month'); // 过滤数据:只保留日期大于等于起始日期的记录 filteredData = originalData.filter(item => { const itemDate = moment(item.date, 'YYYY-MM-DD'); return itemDate.isSameOrAfter(startDate); }); // 更新DOM展示,示例函数 renderData(filteredData); }
- 重置函数,恢复原始数据:
function resetData() { filteredData = [...originalData]; renderData(filteredData); }
- 绑定按钮点击事件:
<button onclick="filterDataByMonths(3)">近3个月</button> <button onclick="filterDataByMonths(6)">近6个月</button> <button onclick="filterDataByMonths(12)">近12个月</button> <button onclick="resetData()">重置</button>
- 渲染数据的示例函数:
function renderData(data) { const list = document.getElementById('data-list'); list.innerHTML = data.map(item => `<li>${item.date}: ${item.score}</li>`).join(''); } // 页面加载时初始化渲染 renderData(filteredData);
React框架实现
如果用React,核心逻辑类似,通过useState管理数据状态:
import React, { useState } from 'react'; import moment from 'moment'; const DataFilter = () => { // 原始数据 const originalData = [ {date: '2023-01-22', score: 57.675}, {date: '2022-11-05', score: 60.675}, {date: '2022-12-11', score: 78.675}, {date: '2022-08-26', score: 81.675} ]; // 状态管理筛选后的数据 const [filteredData, setFilteredData] = useState([...originalData]); const filterDataByMonths = (months) => { const startDate = moment().startOf('day').subtract(months, 'month'); const result = originalData.filter(item => moment(item.date, 'YYYY-MM-DD').isSameOrAfter(startDate) ); setFilteredData(result); }; const resetData = () => { setFilteredData([...originalData]); }; return ( <div> <button onClick={() => filterDataByMonths(3)}>近3个月</button> <button onClick={() => filterDataByMonths(6)}>近6个月</button> <button onClick={() => filterDataByMonths(12)}>近12个月</button> <button onClick={resetData}>重置</button> <ul> {filteredData.map((item, index) => ( <li key={index}>{item.date}: {item.score}</li> ))} </ul> </div> ); }; export default DataFilter;
关键注意点
- 始终从原始数据中筛选,不要直接修改原始数据,确保重置功能正常
- 使用
isSameOrAfter方法比较日期,比格式化字符串对比更可靠,避免字符串排序的潜在问题 startOf('day')确保从当天零点开始计算,不会因当前时间导致筛选误差
内容的提问来源于stack exchange,提问作者makiwumi
相关产品推荐
相关产品推荐

