air-datepicker技术咨询:指定日期禁用、样式自定义及区间限制
我来帮你搞定这几个问题,咱们一步步调整代码,解决日期比较错误、标记特定日期和禁用预约区间的需求:
1. 修复日期比较的问题
你之前直接用字符串比较日期会出问题,比如'2018-10-1'和'2018-5-20'字符串对比时,'2018-10'会被认为比'2018-5'小(因为字符'1'比'5'的ASCII码小),但实际10月的日期更大。
解决办法是统一日期格式为带前导零的YYYY-MM-DD,这样字符串比较就和实际日期顺序一致了。修改你的日期格式化函数:
function getFormattedDate(date) { const year = date.getFullYear(); // 月份和日期补前导零,确保是两位数字 const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; }
同时把disabledDates里的日期也改成统一格式,还可以扩展支持区间:
var disabledDates = [ '2018-05-20', // 单个禁用日期 { start: '2018-05-21', end: '2018-05-23' } // 预约区间 ];
2. 给特定日期添加类名并设置禁用
air-datepicker的onRenderCell回调可以返回classes属性,用来给日期单元格加自定义类,方便你设置不同颜色。咱们先写一个辅助函数判断日期是否在禁用区间内:
function isDateInDisabledRange(currentDateStr) { // 把字符串转成Date对象,方便区间比较 const [year, month, day] = currentDateStr.split('-').map(Number); const currentDate = new Date(year, month - 1, day); for (const item of disabledDates) { if (typeof item === 'object') { const [startYear, startMonth, startDay] = item.start.split('-').map(Number); const startDate = new Date(startYear, startMonth - 1, startDay); const [endYear, endMonth, endDay] = item.end.split('-').map(Number); const endDate = new Date(endYear, endMonth - 1, endDay); // 判断当前日期是否在区间内 if (currentDate >= startDate && currentDate <= endDate) { return true; } } } return false; }
然后修改onRenderCell回调,实现禁用和类名添加:
onRenderCell: function(date, cellType) { const formatted = getFormattedDate(date); if (cellType === 'day') { // 判断是否是单个禁用日期 const isSingleDisabled = disabledDates.some(item => typeof item === 'string' && item === formatted); // 判断是否在禁用区间内 const isInRange = isDateInDisabledRange(formatted); if (isSingleDisabled || isInRange) { return { disabled: true, // 设置日期禁用 classes: 'reserved-date' // 添加自定义类名 }; } return {}; } }
接着在CSS里添加自定义类的样式,让禁用日期显示不同颜色:
.reservation-calendar { display: flex; padding: 20px; } /* 标记禁用日期的样式 */ .reserved-date { background-color: #ffdddd !important; /* 浅红色背景 */ color: #c70000 !important; /* 深红色文字 */ border-radius: 50%; /* 可选:圆形标记 */ }
3. 禁止选择已有预约的区间
上面的代码已经处理了禁用区间内的日期,用户无法点击这些日期。另外,你原来的onSelect逻辑可以优化一下,让选择体验更流畅:
onSelect: function (fd, date) { if (date) { const arrDate = fd.split(","); $startDate.val(arrDate[0]); $endDate.val(arrDate[1] || ''); // 选择完结束日期后自动隐藏日期选择器 if (arrDate[1]) { $('.datepicker').hide(); $startDate.blur(); } // 点击结束日期输入框时,打开日期选择器并保留已选的开始日期 $endDate.off('click').on('click', function () { if ($startDate.val()) { $startDate.datepicker('show'); } }); } }
完整修改后的代码
JavaScript
$(document).ready(function () { // 支持单个日期和区间的禁用列表 var disabledDates = [ '2018-05-20', { start: '2018-05-21', end: '2018-05-23' }, { start: '2018-06-01', end: '2018-06-05' } ]; var $startDate = $('#start'); var $endDate = $('#end'); $startDate.datepicker({ inline: false, range: true, toggleSelected: true, minDate: new Date(), multipleDatesSeparator: ",", dateFormat: 'dd-mm-yyyy', onSelect: function (fd, date) { if(date){ var arrDate = fd.split(","); $startDate.val(arrDate[0]); $endDate.val(arrDate[1] || ''); if(arrDate[1]){ $('.datepicker').hide(); $startDate.blur(); } $endDate.off('click').on('click', function () { if ($startDate.val()) { $startDate.datepicker('show'); } }); } }, onRenderCell: function(date, cellType) { var formatted = getFormattedDate(date); if (cellType == 'day') { const isSingleDisabled = disabledDates.some(item => typeof item === 'string' && item === formatted); const isInRange = isDateInDisabledRange(formatted); if (isSingleDisabled || isInRange) { return { disabled: true, classes: 'reserved-date' }; } return {}; } } }); function getFormattedDate(date) { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } function isDateInDisabledRange(currentDateStr) { const [year, month, day] = currentDateStr.split('-').map(Number); const currentDate = new Date(year, month - 1, day); for (const item of disabledDates) { if (typeof item === 'object') { const [startYear, startMonth, startDay] = item.start.split('-').map(Number); const startDate = new Date(startYear, startMonth - 1, startDay); const [endYear, endMonth, endDay] = item.end.split('-').map(Number); const endDate = new Date(endYear, endMonth - 1, endDay); if (currentDate >= startDate && currentDate <= endDate) { return true; } } } return false; } });
CSS
.reservation-calendar { display: flex; padding: 20px; } .reserved-date { background-color: #ffdddd !important; color: #c70000 !important; border-radius: 50%; }
HTML
<link href="https://cdnjs.cloudflare.com/ajax/libs/air-datepicker/2.2.3/css/datepicker.css" rel="stylesheet"/> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/air-datepicker/2.2.3/js/datepicker.js"></script> <div class="reservation-calendar"> <div class="reservation-calendar__item line"> <input class="start" type="text" id="start" placeholder="开始日期"> </div> - <div class="reservation-calendar__item"> <input class="end" type="text" id="end" placeholder="结束日期"> </div> </div>
这样修改后,你就能正确比较日期、标记禁用日期的样式,并且禁止选择已有预约的区间了~
内容的提问来源于stack exchange,提问作者max
相关产品推荐
相关产品推荐

