VueJS中如何通过起止年月下拉菜单实现表格数据筛选?
嘿,作为Vue新手碰到时间范围筛选的问题太正常啦!我来一步步帮你捋清楚怎么实现,结合你说的四个下拉菜单(起始年、起始月、结束年、结束月)和SQLite数据的情况,咱们分步骤来:
第一步:前端下拉菜单的绑定与数据准备
首先得把下拉菜单和Vue的数据绑定起来,同时生成年份、月份的选项:
- 在
data里定义四个变量:startYear、startMonth、endYear、endMonth,默认可以设为当前年月 - 生成年份选项(比如最近10年)和月份选项(1-12,格式统一为两位数字,比如
01、02) - 用
v-model把下拉菜单和这些变量绑定,确保选中值能实时同步到Vue实例
第二步:实现时间范围筛选逻辑
筛选逻辑有两种方式,根据你的数据量选:
方式一:前端全量筛选(适合数据量小的情况)
用Vue的computed属性自动计算筛选后的数据,这样当下拉框的值变化时,表格会自动更新:
- 把从SQLite获取的原始数据存在
originalData里 - 在
computed里写filteredData,将每条数据的年月转换成YYYY-MM格式的字符串,和选中的起始、结束年月字符串做比较(因为YYYY-MM格式的字符串可以直接按字典序比较大小) - 表格循环渲染
filteredData就行
方式二:数据库层面筛选(适合数据量大的情况)
如果数据量比较多,前端全量筛选会慢,建议直接在SQLite查询时加时间范围条件:
- 监听下拉框的变化,每次选中值改变时,调用方法重新查询数据库
- 用SQLite的
strftime函数处理日期,比如WHERE strftime('%Y-%m', date_column) BETWEEN ? AND ?,把选中的起始年月(YYYY-MM)和结束年月作为参数传入
第三步:添加时间范围校验
避免用户选的结束时间早于起始时间,可以加个校验逻辑:
- 用
watch监听四个下拉框的变化,每次变化时比较起始时间和结束时间 - 如果结束时间更早,弹出提示或者自动调整结束时间为起始时间
完整代码示例整合
<template> <div class="container"> <!-- 时间筛选下拉框 --> <div class="time-filter"> <select v-model="startYear"> <option v-for="year in yearOptions" :key="year" :value="year">{{ year }}</option> </select> <select v-model="startMonth"> <option v-for="month in monthOptions" :key="month" :value="month">{{ month }}</option> </select> <span> 至 </span> <select v-model="endYear"> <option v-for="year in yearOptions" :key="year" :value="year">{{ year }}</option> </select> <select v-model="endMonth"> <option v-for="month in monthOptions" :key="month" :value="month">{{ month }}</option> </select> </div> <!-- 数据表格 --> <table class="data-table"> <thead> <tr> <th>日期</th> <th>其他字段</th> </tr> </thead> <tbody> <tr v-for="item in filteredData" :key="item.id"> <td>{{ item.date }}</td> <td>{{ item.otherField }}</td> </tr> </tbody> </table> </div> </template> <script> export default { data() { return { // 时间筛选变量 startYear: new Date().getFullYear(), startMonth: String(new Date().getMonth() + 1).padStart(2, '0'), endYear: new Date().getFullYear(), endMonth: String(new Date().getMonth() + 1).padStart(2, '0'), // 原始数据(从SQLite获取) originalData: [], // 年份选项(最近10年) yearOptions: [], // 月份选项(两位数字) monthOptions: Array.from({ length: 12 }, (_, i) => String(i + 1).padStart(2, '0')) }; }, computed: { // 前端筛选后的数据集 filteredData() { const startDateStr = `${this.startYear}-${this.startMonth}`; const endDateStr = `${this.endYear}-${this.endMonth}`; return this.originalData.filter(item => { // 假设item.date是YYYY-MM-DD格式,取前7位得到YYYY-MM const itemDateStr = item.date.substring(0, 7); return itemDateStr >= startDateStr && itemDateStr <= endDateStr; }); } }, mounted() { // 生成年份选项 const currentYear = new Date().getFullYear(); this.yearOptions = Array.from({ length: 10 }, (_, i) => currentYear - i); // 初始化从SQLite获取数据 this.fetchOriginalData(); }, watch: { // 监听时间筛选变量变化,校验时间范围 startYear: 'validateDateRange', startMonth: 'validateDateRange', endYear: 'validateDateRange', endMonth: 'validateDateRange' // 如果用数据库筛选,把上面换成: // startYear: 'fetchFilteredDataFromDB', // startMonth: 'fetchFilteredDataFromDB', // endYear: 'fetchFilteredDataFromDB', // endMonth: 'fetchFilteredDataFromDB' }, methods: { // 从SQLite获取全量数据(示例,根据你的实际SQLite使用方式调整) async fetchOriginalData() { // 如果你是在Electron环境用sqlite3: // const sqlite3 = require('sqlite3').verbose(); // const db = new sqlite3.Database('./your-database.db'); // db.all('SELECT * FROM your-table', (err, rows) => { // if (!err) this.originalData = rows; // db.close(); // }); // 如果是通过后端接口获取数据: // const res = await axios.get('/api/your-data'); // this.originalData = res.data; }, // 从SQLite筛选数据(适合大数据量) async fetchFilteredDataFromDB() { const startDateStr = `${this.startYear}-${this.startMonth}`; const endDateStr = `${this.endYear}-${this.endMonth}`; // const sqlite3 = require('sqlite3').verbose(); // const db = new sqlite3.Database('./your-database.db'); // db.all( // `SELECT * FROM your-table WHERE strftime('%Y-%m', date_column) BETWEEN ? AND ?`, // [startDateStr, endDateStr], // (err, rows) => { // if (!err) this.originalData = rows; // db.close(); // } // ); }, // 校验时间范围是否合法 validateDateRange() { const start = new Date(`${this.startYear}-${this.startMonth}`); const end = new Date(`${this.endYear}-${this.endMonth}`); if (start > end) { alert('结束时间不能早于起始时间哦!'); // 自动调整结束时间为起始时间 this.endYear = this.startYear; this.endMonth = this.startMonth; } } } }; </script> <style scoped> .time-filter { margin-bottom: 20px; } .data-table { border-collapse: collapse; width: 100%; } .data-table th, .data-table td { border: 1px solid #ddd; padding: 8px; text-align: left; } </style>
几个关键注意事项
- 日期格式统一:确保SQLite里的日期字段格式是标准的(比如
YYYY-MM-DD),这样前端处理或者SQL查询都不会出错 - 月份格式:一定要把月份处理成两位数字(比如
01而不是1),不然字符串比较的时候会出现2024-1>2024-10的错误 - 性能选择:数据量小(比如几百条)用前端筛选就行,数据量大(几千条以上)尽量用数据库层面筛选,减少前端压力
如果还有具体的细节比如SQLite的使用方式、数据格式不匹配之类的问题,随时调整就行!
内容的提问来源于stack exchange,提问作者Gertrude Lowes
相关产品推荐
相关产品推荐

