返回

PrimeVue Datepicker 扩展: 实现预设日期范围选择

vue.js

PrimeVue Datepicker 预设日期范围实现

问题分析

PrimeVue 的 Datepicker 组件是一个强大且常用的日期选择器,但其本身并没有提供内置的预设日期范围功能,如“本周”、“上周”、“上个月”等。开发者希望扩展 Datepicker,实现类似上图所示的日期预设功能,这在许多实际应用中都是很常见的要求。尝试使用 slot 似乎不能直接满足需求。考虑 Calendar 组件是否更为适合。

解决方案一:扩展 Datepicker 组件

一种可行的方式是通过组合 Datepicker 组件与其他元素,自定义预设选择的交互逻辑。其原理是将预设日期范围的操作独立出来,并利用 Datepicker 组件的日期选择能力来实现。

  1. 创建预设选项列表 :定义包含日期范围的选项数组,每个选项对应一个特定的日期范围,例如“本周”、“上周”、“上个月”。每个选项可以关联一个返回开始日期和结束日期的函数。

    const datePresets = [
    {
      label: '本周',
      calculateRange: () => {
        const now = new Date();
        const start = new Date(now);
        const dayOfWeek = now.getDay();
        start.setDate(now.getDate() - dayOfWeek);
        const end = new Date(start);
        end.setDate(start.getDate() + 6);
          return { start, end };
      },
    },
    {
      label: '上周',
      calculateRange: () => {
          const now = new Date();
        const today = now.getDay();
          const lastWeekStart = new Date();
          lastWeekStart.setDate(now.getDate() - today - 7);
          const lastWeekEnd = new Date(lastWeekStart);
        lastWeekEnd.setDate(lastWeekStart.getDate() + 6);
         return { start:lastWeekStart, end:lastWeekEnd};
    
      },
    },
      {
        label: "本月",
        calculateRange: () => {
            const now = new Date();
            const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
            const endOfMonth = new Date(now.getFullYear(), now.getMonth()+ 1,0)
            return { start: startOfMonth, end: endOfMonth};
      }
      }
      // ... 添加更多预设范围
    ];
    
    
  2. 构建UI : 在Datepicker组件旁边创建一个下拉选择框或者按钮列表来显示定义的预设选项,当用户选择某个预设选项时,使用calculateRange方法计算对应的开始和结束日期。

  3. 更新DatePicker : 使用编程方式更新 Datepicker 组件的值。 利用Datepicker的v-model来绑定选择的日期。当预设范围选定后,同步更新DatePicker的值。需要注意:确保绑定到v-model的变量是具有startend属性的对象。

    <template>
    <div style="display:flex;align-items:center;">
        <Dropdown :modelValue="selectedPreset"  :options="datePresets" optionLabel="label" @update:modelValue="updateRange"/>
        <Datepicker v-model="selectedDates"  selectionMode="range" />
    
    </div>
    </template>
    <script setup>
        import { ref } from 'vue'
        import Datepicker from 'primevue/datepicker';
        import Dropdown from 'primevue/dropdown'
    
    
         const selectedPreset = ref(null);
         const selectedDates = ref({ start: null, end: null });
    
    
        const datePresets = [
    {
      label: '本周',
      calculateRange: () => {
        const now = new Date();
        const start = new Date(now);
        const dayOfWeek = now.getDay();
        start.setDate(now.getDate() - dayOfWeek);
        const end = new Date(start);
        end.setDate(start.getDate() + 6);
          return { start, end };
      },
    },
    {
      label: '上周',
      calculateRange: () => {
          const now = new Date();
        const today = now.getDay();
          const lastWeekStart = new Date();
          lastWeekStart.setDate(now.getDate() - today - 7);
          const lastWeekEnd = new Date(lastWeekStart);
        lastWeekEnd.setDate(lastWeekStart.getDate() + 6);
         return { start:lastWeekStart, end:lastWeekEnd};
    
      },
    },
     {
        label: "本月",
        calculateRange: () => {
            const now = new Date();
            const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
            const endOfMonth = new Date(now.getFullYear(), now.getMonth()+ 1,0)
            return { start: startOfMonth, end: endOfMonth};
      }
      }
      // ... add more preset range
    ];
     const updateRange = (preset) => {
        if (preset?.calculateRange) {
            const range = preset.calculateRange();
           selectedDates.value.start = range.start
           selectedDates.value.end = range.end
       }
    
    
      }
    </script>
    

操作步骤:

  1. 在 Vue 项目中,安装 PrimeVue 的 datepickerdropdown 组件:
npm install primevue
npm install primeicons
  1. 复制上述 Vue 组件代码并引入所需的依赖。

  2. 确保 PrimeVue 已配置正确,以便组件正常工作。

  3. 调整样式以获得更好的UI显示。

解决方案二:使用 Calendar 组件进行拓展

Calendar 组件同样支持范围选择模式,它更侧重于直接操作日期,而不是内置预设。可以通过与辅助元素的配合来实现预设效果。

  1. 布局 。 使用一个div来包含 Calendar 和额外的按钮或者选项元素。
  2. 预设函数 ,将之前计算预设范围的方法保持不变。
  3. 操作逻辑 。 当用户点击预设的按钮或选项时,调用对应的预设函数,使用编程方式更新Calendar的值。确保v-model的值格式和Calendar保持一致,例如都为包含startDateendDate的对象。

代码示例

<template>
<div style="display:flex;align-items:center;">
     <Dropdown :modelValue="selectedPreset"  :options="datePresets" optionLabel="label" @update:modelValue="updateRange"/>
        <Calendar v-model="selectedDates" selectionMode="range" />
</div>
</template>

<script setup>

        import { ref } from 'vue'
    import Calendar from 'primevue/calendar';
      import Dropdown from 'primevue/dropdown'



        const selectedPreset = ref(null);
         const selectedDates = ref({ startDate: null, endDate: null });


       const datePresets = [
        {
          label: '本周',
          calculateRange: () => {
            const now = new Date();
            const start = new Date(now);
            const dayOfWeek = now.getDay();
            start.setDate(now.getDate() - dayOfWeek);
            const end = new Date(start);
            end.setDate(start.getDate() + 6);
              return { startDate:start, endDate:end };
          },
        },
        {
          label: '上周',
          calculateRange: () => {
              const now = new Date();
            const today = now.getDay();
              const lastWeekStart = new Date();
              lastWeekStart.setDate(now.getDate() - today - 7);
              const lastWeekEnd = new Date(lastWeekStart);
            lastWeekEnd.setDate(lastWeekStart.getDate() + 6);
             return { startDate:lastWeekStart, endDate:lastWeekEnd};

          },
        },
         {
            label: "本月",
            calculateRange: () => {
                const now = new Date();
                const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
                const endOfMonth = new Date(now.getFullYear(), now.getMonth()+ 1,0)
                return { startDate: startOfMonth, endDate: endOfMonth};
        }
        }

      ];

        const updateRange = (preset) => {

        if (preset?.calculateRange) {
             const range = preset.calculateRange();
           selectedDates.value = range;


        }


      }


</script>

操作步骤:

  1. 在Vue项目中,安装PrimeVue 的 calendardropdown 组件(参考解决方案一)。
  2. 将上述代码片段添加到Vue组件中。
  3. 确保PrimeVue 正常初始化。
  4. 根据项目需求,对样式和UI交互进行自定义。

额外的考虑

  • 国际化: 如果需要支持多语言环境,注意将预设标签本地化。
  • 用户体验: 提供合适的视觉反馈,当预设选项选择后,Datepicker 或者 Calendar 可以高亮显示选择的范围。

选择哪种方法取决于具体的需求和偏好。 两种方法都能够为 PrimeVue Datepicker 或 Calendar 组件增加预设范围选择的功能。

没有添加相关的资源链接,因为提供的代码示例可以直接解决问题。