当前位置:首页 > VUE

vue封装datepicker实现

2026-02-11 05:49:02VUE

vue封装datepicker实现

基础组件结构

使用Vue的单文件组件形式封装DatePicker,核心结构包含模板、脚本和样式三部分。模板部分定义日期选择器的UI布局,脚本处理逻辑,样式负责外观。

模板部分示例:

vue封装datepicker实现

<template>
  <div class="date-picker">
    <input 
      type="text" 
      v-model="displayValue" 
      @click="togglePicker"
      @blur="handleBlur"
    />
    <div class="calendar" v-show="isOpen">
      <div class="header">
        <button @click="prevMonth">‹</button>
        <span>{{ currentMonth }}</span>
        <button @click="nextMonth">›</button>
      </div>
      <div class="days">
        <div v-for="day in days" :key="day" class="day-header">{{ day }}</div>
      </div>
      <div class="dates">
        <div 
          v-for="date in visibleDates" 
          :key="date.getTime()"
          @click="selectDate(date)"
          :class="{ 
            'selected': isSelected(date), 
            'current-month': isCurrentMonth(date),
            'today': isToday(date)
          }"
        >
          {{ date.getDate() }}
        </div>
      </div>
    </div>
  </div>
</template>

核心逻辑实现

脚本部分处理日期选择的核心功能,包括日期生成、月份切换和选择逻辑。

vue封装datepicker实现

<script>
export default {
  data() {
    return {
      selectedDate: null,
      currentDate: new Date(),
      isOpen: false,
      days: ['日', '一', '二', '三', '四', '五', '六']
    }
  },
  computed: {
    displayValue() {
      return this.selectedDate 
        ? `${this.selectedDate.getFullYear()}-${this.selectedDate.getMonth() + 1}-${this.selectedDate.getDate()}`
        : '';
    },
    currentMonth() {
      return `${this.currentDate.getFullYear()}年${this.currentDate.getMonth() + 1}月`;
    },
    visibleDates() {
      const dates = [];
      const firstDay = new Date(
        this.currentDate.getFullYear(),
        this.currentDate.getMonth(),
        1
      );
      const lastDay = new Date(
        this.currentDate.getFullYear(),
        this.currentDate.getMonth() + 1,
        0
      );

      const prevMonthDays = firstDay.getDay();
      const nextMonthDays = 6 - lastDay.getDay();

      const startDate = new Date(firstDay);
      startDate.setDate(startDate.getDate() - prevMonthDays);

      const endDate = new Date(lastDay);
      endDate.setDate(endDate.getDate() + nextMonthDays);

      while (startDate <= endDate) {
        dates.push(new Date(startDate));
        startDate.setDate(startDate.getDate() + 1);
      }

      return dates;
    }
  },
  methods: {
    togglePicker() {
      this.isOpen = !this.isOpen;
    },
    handleBlur() {
      setTimeout(() => {
        this.isOpen = false;
      }, 200);
    },
    prevMonth() {
      this.currentDate = new Date(
        this.currentDate.getFullYear(),
        this.currentDate.getMonth() - 1,
        1
      );
    },
    nextMonth() {
      this.currentDate = new Date(
        this.currentDate.getFullYear(),
        this.currentDate.getMonth() + 1,
        1
      );
    },
    selectDate(date) {
      this.selectedDate = date;
      this.$emit('input', date);
      this.isOpen = false;
    },
    isSelected(date) {
      return this.selectedDate && 
        date.getFullYear() === this.selectedDate.getFullYear() &&
        date.getMonth() === this.selectedDate.getMonth() &&
        date.getDate() === this.selectedDate.getDate();
    },
    isCurrentMonth(date) {
      return date.getMonth() === this.currentDate.getMonth();
    },
    isToday(date) {
      const today = new Date();
      return date.getFullYear() === today.getFullYear() &&
        date.getMonth() === today.getMonth() &&
        date.getDate() === today.getDate();
    }
  }
}
</script>

样式优化

添加基础样式增强用户体验,包括日历布局、日期状态样式和过渡效果。

<style scoped>
.date-picker {
  position: relative;
  display: inline-block;
}

input {
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.calendar {
  position: absolute;
  top: 100%;
  left: 0;
  width: 280px;
  margin-top: 5px;
  padding: 10px;
  background: white;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  z-index: 1000;
}

.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: 5px;
}

.day-header {
  text-align: center;
  font-weight: bold;
}

.dates {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 5px;
}

.dates > div {
  text-align: center;
  padding: 5px;
  cursor: pointer;
  border-radius: 3px;
}

.dates > div:hover {
  background: #f0f0f0;
}

.dates > div.current-month {
  color: #333;
}

.dates > div:not(.current-month) {
  color: #aaa;
}

.dates > div.selected {
  background: #409eff;
  color: white;
}

.dates > div.today {
  font-weight: bold;
  color: #409eff;
}
</style>

组件使用方式

封装完成后,可以在父组件中直接使用,并通过v-model绑定日期值。

<template>
  <div>
    <date-picker v-model="selectedDate" />
  </div>
</template>

<script>
import DatePicker from './DatePicker.vue';

export default {
  components: { DatePicker },
  data() {
    return {
      selectedDate: null
    }
  }
}
</script>

功能扩展建议

  • 添加日期范围选择功能
  • 支持国际化显示
  • 增加日期禁用功能
  • 添加动画过渡效果
  • 支持自定义日期格式

通过以上步骤可以实现一个基础的Vue日期选择器组件,根据实际需求可以进一步扩展功能。组件化的设计使其易于复用和维护,样式部分使用scoped避免污染全局样式。

标签: vuedatepicker
分享给朋友:

相关文章

vue播放倍速怎么实现

vue播放倍速怎么实现

实现Vue播放倍速的方法 在Vue中实现播放倍速功能通常涉及HTML5的<video>元素或第三方播放器库。以下是几种常见实现方式: 使用原生HTML5 video元素 通过ref获取v…

vue实现继承语法糖

vue实现继承语法糖

在Vue中实现继承可以通过多种方式模拟类继承的效果,以下是常见的几种方法: 使用mixins实现逻辑复用 通过Vue的mixins机制共享组件选项,达到类似继承的效果: const BaseC…

vue实现发表

vue实现发表

Vue 实现发表功能 在 Vue 中实现发表功能通常涉及表单处理、数据绑定和网络请求。以下是实现步骤和代码示例: 表单设计与数据绑定 创建一个表单用于输入发表内容,使用 v-model 进行数据双…

vue实现https

vue实现https

Vue 中实现 HTTPS 的步骤 在 Vue 项目中实现 HTTPS 主要涉及开发环境配置和生产环境部署。以下是具体方法: 开发环境配置(Vue CLI 或 Vite) 使用 mkcert 生成…

vue 实现pdf

vue 实现pdf

在Vue中实现PDF功能 在Vue项目中实现PDF功能通常涉及PDF生成、预览或下载。以下是几种常见实现方式: 使用vue-pdf库预览PDF 安装依赖: npm install vue-pdf…

vue实现删除

vue实现删除

Vue 实现删除功能的方法 在 Vue 中实现删除功能通常涉及以下几个步骤: 数据绑定与列表渲染 使用 v-for 指令渲染列表数据,并为每个项绑定唯一标识符(如 id)。例如: <…