initialDays的map函数内使用find查找事件数组元素报错及匹配异常
问题
开发动态渲染事件的日历,通过代码生成日期数组并展示,同时维护包含事件详情的events对象:
- 在
initialDays的map函数外调用events.find能正常匹配对应日期的事件 - 在
map函数内使用以下代码时触发报错:
events.find((item) => { return item.datetime == dates })
报错信息:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'length')
- 当前所有日期都被填充了全部事件,而非仅匹配日期的事件
原createDays函数代码:
createDays() { this.today = startOfToday() this.formatedDate = format(this.today, 'MMM, yyyy') this.currentMonth = this.formatedDate this.getNewDays = parse(this.currentMonth, 'MMM, yyyy', new Date()) this.firstDayCurrentMonth = parse(this.currentMonth, 'MMM, yyyy', new Date()) let initialDays = eachDayOfInterval({ start: startOfWeek(this.getNewDays, {weekStartsOn: 1}), end: endOfWeek(endOfMonth(this.getNewDays), {weekStartsOn: 1}) }) let events = [{ id: 3, name: 'Date night', time: '6PM', datetime: '2022-10-10', href: '#' }, { id: 4, name: 'Date night', time: '6PM', datetime: '2022-10-12', href: '#' }, { id: 3, name: 'Date night', time: '6PM', datetime: '2022-10-13', href: '#' }] events = events.map((events) => { return { id: events.id, name: events.name, time: events.time, datetime: events.datetime, href: events.href } }) const findevent = events.find((item) => { return item.datetime === '2022-10-10' }) console.log(findevent) initialDays = initialDays.map((dates) => { return { date: format(dates, 'yyyy-MM-dd'), isCurrentMonth: isSameMonth(this.getNewDays, dates), isToday: isToday(dates), isSelected: isSameDay(dates, this.today), events: events.find((item) => { return item.datetime == dates }) } }) this.days = initialDays },
当前返回的日期对象示例(错误状态):
{ "date": "2022-10-22", "isCurrentMonth": true, "isToday": false, "isSelected": false, "events": [ { "id": 3, "name": "Date night", "time": "6PM", "datetime": "2022-10-10", "href": "#" }, { "id": 4, "name": "Date night", "time": "6PM", "datetime": "2022-10-12", "href": "#" }, { "id": 3, "name": "Date night", "time": "6PM", "datetime": "2022-10-13", "href": "#" } ] }
解决方案
问题根源
- 类型不匹配导致查找失败:
initialDays.map中的dates是Date对象,而events里的datetime是字符串格式(如'2022-10-10'),直接用==比较会返回false,find找不到匹配项时返回undefined,后续渲染代码尝试读取undefined.length触发报错。 - 事件匹配逻辑错误:若需要展示某天的所有事件,应该用
filter而非find(find仅返回第一个匹配项);同时错误的比较逻辑导致意外赋值了整个事件数组。
修复步骤
- 统一日期格式进行比较:将
map中的dates格式化为与events.datetime一致的yyyy-MM-dd字符串,再进行匹配。 - 使用
filter获取当日所有事件:如果某天可能有多个事件,用filter替代find;若仅需单个事件,保留find但需处理undefined的情况(如返回空数组或null)。 - 避免意外赋值整个事件数组:确保
events字段仅赋值匹配的事件集合。
修正后的代码
createDays() { this.today = startOfToday() this.formatedDate = format(this.today, 'MMM, yyyy') this.currentMonth = this.formatedDate this.getNewDays = parse(this.currentMonth, 'MMM, yyyy', new Date()) this.firstDayCurrentMonth = parse(this.currentMonth, 'MMM, yyyy', new Date()) let initialDays = eachDayOfInterval({ start: startOfWeek(this.getNewDays, {weekStartsOn: 1}), end: endOfWeek(endOfMonth(this.getNewDays), {weekStartsOn: 1}) }) let events = [{ id: 3, name: 'Date night', time: '6PM', datetime: '2022-10-10', href: '#' }, { id: 4, name: 'Date night', time: '6PM', datetime: '2022-10-12', href: '#' }, { id: 3, name: 'Date night', time: '6PM', datetime: '2022-10-13', href: '#' }] // 简化对象复制逻辑 events = events.map(event => ({...event})) const findevent = events.find((item) => { return item.datetime === '2022-10-10' }) console.log(findevent) initialDays = initialDays.map((dates) => { const dateStr = format(dates, 'yyyy-MM-dd') // 筛选当日所有事件,若无则返回空数组 const dayEvents = events.filter(item => item.datetime === dateStr) return { date: dateStr, isCurrentMonth: isSameMonth(this.getNewDays, dates), isToday: isToday(dates), isSelected: isSameDay(dates, this.today), events: dayEvents } }) this.days = initialDays },
额外优化
可以提前将events按datetime分组,避免每次map都遍历整个事件数组,提升性能:
// 提前按日期分组事件 const eventsByDate = {} events.forEach(event => { if (!eventsByDate[event.datetime]) { eventsByDate[event.datetime] = [] } eventsByDate[event.datetime].push(event) }) // 后续map中直接获取当日事件 const dayEvents = eventsByDate[dateStr] || []
内容的提问来源于stack exchange,提问作者DMantas
相关产品推荐
相关产品推荐

