Devextreme-vue + Vue2日历下拉框的使用

发布于:2025-08-14 ⋅ 阅读:(23) ⋅ 点赞:(0)
npm install devextreme@22.2.6 devextreme-vue@22.2.6

效果图:

<template>
  <div style="padding: 20px">
    <!-- 日期选择框 -->
    <DxDateBox
      v-model="selectedDate"
      displayFormat="yyyy/M/d"
      placeholder="请选择大于最近版本且不早于今天的有效日期"
      :min="minSelectableDate"
      :show-clear-button="true"
      :use-calendar="true"
      :width="200"
      :disabled="loading" 
      @value-changed="handleDateChange"
    />

    <!-- 提交按钮 -->
    <DxButton
      text="提交"
      type="default"
      styling-mode="contained"
      style="margin-left: 10px"
      :width="100"
      :disabled="!selectedDateStr || loading"
      @click="submit"
    />
  </div>
</template>

<script>
import { DxDateBox } from 'devextreme-vue/date-box';
import { DxButton } from 'devextreme-vue/button';
import 'devextreme/dist/css/dx.light.css';
import moment from 'moment';

// 中文支持
import { locale, loadMessages } from 'devextreme/localization';
import dxMessagesZh from 'devextreme/localization/messages/zh';
loadMessages(dxMessagesZh);
locale('zh-CN');

export default {
  components: { DxDateBox, DxButton },


  data() {
    return {
      list: [], // 初始为空,等待后端加载
      selectedDate: null,
      selectedDateStr: '',
      loading: true // 控制加载状态
    };
  },
  

  created() {
    // 模拟异步从后端加载数据
    setTimeout(() => {
      this.list = [
        { id: 1, date: '2025-08-09', isValid: true },
        { id: 2, date: '2025-08-10', isValid: true },
        { id: 3, date: '2025-08-05', isValid: false },
        { id: 4, date: '2025-08-08', isValid: true },
        { id: 5, date: '2025-08-15', isValid: true }
      ];
      this.loading = false; // 关闭加载状态
    }, 800); // 模拟网络延迟
  },


  computed: {
    /**
     * 功能:计算最小可选日期
     * 
     * 原理:初始化改变了依赖的list 又因为list是响应数据vue监听到会触发minSelectableDate方法   
     * 
     * 业务:用户可选的日期必须同时满足两个条件
     *       1.大于 list 中所有 isValid: true 记录的 最大日期
     *       2.大于等于今天(当前系统日期)
     */
    minSelectableDate() {
      const latestValidDate = this.findLatestValidDate(this.list, 'date');
      // 当前日期(今天)00:00:00
      const today = moment().startOf('day');

      // 历史版本最大有效日期加上 1 天(得到“最大有效日期的下一天”)
      const nextDayAfterLatest = latestValidDate ? latestValidDate.clone().add(1, 'day').startOf('day') : null;

      // 最小可选日期 == 两者中较大的(即更晚的日期)
      const minDate = nextDayAfterLatest ? moment.max(nextDayAfterLatest, today) : today;

      return minDate.toDate();
    }
  },


  methods: {
    // 找出 list 中 isValid === true 的记录,并返回指定字段(生效日期)的最大日期
    findLatestValidDate(list, fieldName) {
      let max = null;
      for (const item of list) {
        if (!item.isValid) continue;
        const date = moment(item[fieldName], 'YYYY-MM-DD');
        if (!date.isValid()) continue;
        if (max === null || date.isAfter(max, 'day')) {
          max = date;
        }
      }
      return max;
    },

    /**
     * 功能:更新要提交的表单数据
     * 
     * e 是 DevExtreme 的事件对象,用户选择下来日期自动带过来
     * 结构: e = {
     *              value: Date | null,  // 用户选中的日期(JavaScript Date 对象),或 null(清空时)
     *              previousValue: ...   // 上一次的值(这里没用到)
     *            }
     */
    handleDateChange(e) {
      this.selectedDateStr = e.value ? moment(e.value).format('YYYY/M/D') : '';
    },

    /**
     * 功能:模拟保存并提交表单
     */
    submit() {
      if (!this.selectedDateStr) return;
      alert(`已提交:${this.selectedDateStr}(模拟成功)`);
    }
  }
};
</script>

<style scoped>
.dx-datebox {
  margin-right: 10px;
}
</style>


网站公告

今日签到

点亮在社区的每一天
去签到