Vue.js中基于对象数据生成日期区间数组并展示视图的实现方法问询
Got it, let's break down how to solve this problem. You need to convert each dateFrom/dateTo range into an array of individual dates, map those dates to the corresponding weekly schedule, and finally display everything in a table. Here's a complete, ready-to-use implementation:
Step 1: Add a Method to Generate Date Ranges
First, create a reusable method that takes start and end date strings, then returns an array of formatted dates (YYYY-MM-DD):
methods: { generateDateRange(startDateStr, endDateStr) { const dates = []; const startDate = new Date(startDateStr); const endDate = new Date(endDateStr); let currentDate = new Date(startDate); // Clone to avoid mutating the original date while (currentDate <= endDate) { // Format date to YYYY-MM-DD using ISO string split const formattedDate = currentDate.toISOString().split('T')[0]; dates.push(formattedDate); // Increment the date by one day currentDate.setDate(currentDate.getDate() + 1); } return dates; } }
Step 2: Create a Computed Property to Process Raw Data
Use a computed property to transform your nested datas into a flat array of schedule entries (one per date per employee). This will automatically update if your raw data changes:
computed: { processedScheduleData() { return this.datas.flatMap(employee => { // Flatten each employee's schedule_time entries return employee.schedule_time.flatMap(schedule => { // Generate the full date range for this schedule block const dateRange = this.generateDateRange(schedule.dateFrom, schedule.dateTo); // Create a map of day numbers to schedule details for quick lookup const dayScheduleMap = schedule.schedule_day.reduce((map, dayEntry) => { // Map day names to numbers (matches Date.getDay(): 0=Sun, 1=Mon, ..., 6=Sat) const dayNumber = { Monday: 1, Tuesday: 2, Wednesday: 3, Thursday: 4, Friday: 5, Saturday: 6, Sunday: 0 }[dayEntry.days]; map[dayNumber] = dayEntry; return map; }, {}); // Convert each date in the range to a schedule entry return dateRange.map(dateStr => { const date = new Date(dateStr); const dayNum = date.getDay(); const matchedSchedule = dayScheduleMap[dayNum] || null; return { employeeName: employee.name, date: dateStr, dayOfWeek: Object.keys(dayScheduleMap).find(key => parseInt(key) === dayNum) || 'Weekend', startTime: matchedSchedule ? matchedSchedule.startTime : 'N/A', endTime: matchedSchedule ? matchedSchedule.endTime : 'N/A' }; }); }); }); } }
Step 3: Render the Table in Your Template
Add a table to display the processed data. Each row represents one employee's schedule for a single date:
<template> <div class="schedule-table"> <table border="1" cellpadding="8" cellspacing="0"> <thead> <tr> <th>Employee Name</th> <th>Date</th> <th>Day of Week</th> <th>Start Time</th> <th>End Time</th> </tr> </thead> <tbody> <tr v-for="entry in processedScheduleData" :key="`${entry.employeeName}-${entry.date}`"> <td>{{ entry.employeeName }}</td> <td>{{ entry.date }}</td> <td>{{ entry.dayOfWeek }}</td> <td>{{ entry.startTime }}</td> <td>{{ entry.endTime }}</td> </tr> </tbody> </table> </div> </template>
Full Component Code
Putting it all together, your complete component will look like this:
<template> <div class="schedule-table"> <table border="1" cellpadding="8" cellspacing="0"> <thead> <tr> <th>Employee Name</th> <th>Date</th> <th>Day of Week</th> <th>Start Time</th> <th>End Time</th> </tr> </thead> <tbody> <tr v-for="entry in processedScheduleData" :key="`${entry.employeeName}-${entry.date}`"> <td>{{ entry.employeeName }}</td> <td>{{ entry.date }}</td> <td>{{ entry.dayOfWeek }}</td> <td>{{ entry.startTime }}</td> <td>{{ entry.endTime }}</td> </tr> </tbody> </table> </div> </template> <script> export default { data(){ return { datas: [ { "id": 1, "name": "Sandra Brooke", "schedule_time": [ { "id": 1, "dateFrom": "2022-01-24", "dateTo": "2022-02-28", "schedule_day": [ {"id":1,"days": "Monday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":2,"days": "Tuesday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":3,"days": "Wednesday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":4,"days": "Thursday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":5,"days": "Friday", "startTime": "08:00:00", "endTime": "16:00:00"}, ] } ] }, { "id": 2, "name": "Michael Anderson", "schedule_time": [ { "id": 1, "dateFrom": "2022-01-24", "dateTo": "2022-02-28", "schedule_day": [ {"id":1,"days": "Monday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":2,"days": "Tuesday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":3,"days": "Wednesday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":4,"days": "Thursday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":5,"days": "Friday", "startTime": "08:00:00", "endTime": "16:00:00"}, ] } ] }, { "id": 3, "name": "Sarah Black", "schedule_time": [ { "id": 1, "dateFrom": "2022-01-24", "dateTo": "2022-02-28", "schedule_day": [ {"id":1,"days": "Monday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":2,"days": "Tuesday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":3,"days": "Wednesday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":4,"days": "Thursday", "startTime": "08:00:00", "endTime": "18:00:00"}, {"id":5,"days": "Friday", "startTime": "08:00:00", "endTime": "16:00:00"}, ] } ] }, ], } }, methods: { generateDateRange(startDateStr, endDateStr) { const dates = []; const startDate = new Date(startDateStr); const endDate = new Date(endDateStr); let currentDate = new Date(startDate); while (currentDate <= endDate) { const formattedDate = currentDate.toISOString().split('T')[0]; dates.push(formattedDate); currentDate.setDate(currentDate.getDate() + 1); } return dates; } }, computed: { processedScheduleData() { return this.datas.flatMap(employee => { return employee.schedule_time.flatMap(schedule => { const dateRange = this.generateDateRange(schedule.dateFrom, schedule.dateTo); const dayScheduleMap = schedule.schedule_day.reduce((map, dayEntry) => { const dayNumber = { Monday: 1, Tuesday: 2, Wednesday: 3, Thursday: 4, Friday: 5, Saturday: 6, Sunday: 0 }[dayEntry.days]; map[dayNumber] = dayEntry; return map; }, {}); return dateRange.map(dateStr => { const date = new Date(dateStr); const dayNum = date.getDay(); const matchedSchedule = dayScheduleMap[dayNum] || null; return { employeeName: employee.name, date: dateStr, dayOfWeek: Object.keys(dayScheduleMap).find(key => parseInt(key) === dayNum) || 'Weekend', startTime: matchedSchedule ? matchedSchedule.startTime : 'N/A', endTime: matchedSchedule ? matchedSchedule.endTime : 'N/A' }; }); }); }); } } } </script> <style scoped> .schedule-table { margin: 20px; } table { width: 100%; border-collapse: collapse; } th { background-color: #f0f0f0; } </style>
Key Details:
- The
generateDateRangemethod safely clones dates to avoid mutating the original start date value. - The computed property uses
flatMapto flatten nested arrays, making it easy to iterate over in the template. - We map day names to
Date.getDay()values for fast lookup of the corresponding schedule entry. - Dates without a schedule (like weekends) show "N/A" for times and "Weekend" as the day of week.
内容的提问来源于stack exchange,提问作者Annisa Lianda

